Skip to content

iOS Query Builder Crash #724

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
1 task done
GabrielAraujo opened this issue Apr 25, 2025 · 4 comments
Open
1 task done

iOS Query Builder Crash #724

GabrielAraujo opened this issue Apr 25, 2025 · 4 comments
Assignees
Labels
bug Something isn't working

Comments

@GabrielAraujo
Copy link

Description

App is crashing when trying to build a Boolean query condition on iOS. The crash happens on the the C/C++ layer so I couldn't investigate more.

According to this comment on another thread the method obx_dart_query_find_ptr was supposed to be of internal usage only?

Could you help? This is affecting a portion of our crash free user rate and damaging the company reputation.

Is there an existing issue?

Build info

  • objectbox version: 4.0.3
  • Flutter/Dart version: 3.27.3
  • Build OS: macOS
  • Deployment OS or device: iOS 18.3.2

Steps to reproduce

I couldn't reproduce this issue myself but it is happening on a portion of our production users.

Expected behavior

To not crash when building query condition

Actual behavior

App crashes

Code

Code

Entity

import 'package:objectbox/objectbox.dart';

@Entity()
class TemplateSectionObx {
  TemplateSectionObx({
    this.id = 0,
    required this.templateId,
    this.isNew = false,
    this.hasSynced = true,
    this.alwaysPageBreak = false,
    this.disclaimerText,
    this.icon,
    this.identifier,
    this.isDefault = false,
    this.isOverview = false,
    this.lockItemAdding = false,
    this.locked = false,
    this.name,
    this.notes = '',
    this.priority = 0,
    this.qualityScoreMultiplier,
    this.createdAt,
    this.updatedAt,
    this.deletedAt,
  });

  @Id(assignable: true)
  int id;

  @Index()
  final int templateId;

  @Index()
  final bool hasSynced;

  final bool isNew;
  final bool alwaysPageBreak;
  final String? disclaimerText;
  final String? icon;
  final String? identifier;
  final bool isDefault;
  final bool isOverview;
  final bool lockItemAdding;
  final bool locked;
  final String? name;
  final String notes;
  final int priority;
  final int? qualityScoreMultiplier;

  @Property(type: PropertyType.date)
  final DateTime? createdAt;

  @Property(type: PropertyType.date)
  final DateTime? updatedAt;

  final String? deletedAt;
}

Failing Query

  final query = box.query(TemplateSectionObx_.hasSynced.equals(false)).build();

  final results = query.find();
  query.close();
  objectbox: ^4.0.3
  objectbox_flutter_libs: any
...
  objectbox_generator: any

Logs, stack traces

Logs

ObjectBox deps

├── objectbox 4.0.3
│   ├── flat_buffers 23.5.26
│   ├── collection...
│   ├── ffi...
│   ├── meta...
│   └── path...
├── objectbox_flutter_libs 4.0.3
│   ├── flutter...
│   ├── objectbox...
│   └── path_provider...
├── objectbox_generator 4.0.3
│   ├── analyzer...
│   ├── build...
│   ├── collection...
│   ├── dart_style...
│   ├── glob...
│   ├── http...
│   ├── objectbox...
│   ├── path...
│   ├── pointycastle...
│   ├── pubspec_parse...
│   ├── source_gen...
│   └── yaml...

Crash

Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x0000000000000020
Exception Codes: 0x0000000000000001, 0x0000000000000020
VM Region Info: 0x20 is not in any region.  Bytes before following region: 4332404704
      REGION TYPE                 START - END      [ VSIZE] PRT/MAX SHRMOD  REGION DETAIL
      UNUSED SPACE AT START
--->  
      __TEXT                   1023b4000-1023bc000 [   32K] r-x/r-x SM=COW  /var/containers/Bundle/Application/CF850A06-4A29-40CB-AA6E-CF6F7E23BE93/Runner.app/Runner
Termination Reason: SIGNAL 11 Segmentation fault: 11
Terminating Process: exc handler [14185]

Triggered by Thread:  19

Thread

Thread 19 Crashed:
0   ObjectBox                     	0x00000001043d50c0 obx_dart_query_find_ptr + 589584
1   ObjectBox                     	0x0000000104329028 obx_qb_equals_int + 76
2   App                           	0x000000011254d53c stub CallNativeThroughSafepoint + 88
3   App                           	0x00000001128553c0 ObjectBoxC._qb_order.#ffiClosure231 + 116 (objectbox_c.dart:4938)
4   App                           	0x0000000112ed3d1c ObjectBoxC.qb_equals_int (#2) + 100 (objectbox_c.dart:4378)
5   App                           	0x0000000112ed3c90 ObjectBoxC.qb_equals_int + 44 (objectbox_c.dart:4373)
6   App                           	0x0000000112ed33d0 IntegerCondition._op1 + 96 (query.dart:680)
7   App                           	0x0000000112ed2e70 IntegerCondition._apply + 156 (query.dart:686)
8   App                           	0x00000001127d58ac Condition._applyFull + 56 (query.dart:537)
9   App                           	0x00000001127d4a24 _QueryBuilder._applyCondition + 56 (builder.dart:146)
10  App                           	0x00000001127d4a24 QueryBuilder.build + 56 (builder.dart:17)
11  App                           	0x0000000112860424 fetchUnsynced (#3) + 196 (template_section_plugin.dart:200)
12  App                           	0x0000000112860348 registerTemplateSectionObxPlugin.<anonymous closure> (#3) + 48 (template_section_plugin.dart:81)
13  App                           	0x0000000112852090 runWithErrorRecovery + 252 (isolate_manager.dart:249)
14  App                           	0x000000011285ed40 registerTemplateSectionObxPlugin + 1212 (template_section_plugin.dart:77)
15  App                           	0x0000000112851ca8 isolateEntryPoint.<anonymous closure> + 848 (isolate_manager.dart:365)
16  App                           	0x0000000112dc2d88 RootZone.runUnaryGuarded + 124 (zone.dart:1609)
17  App                           	0x0000000112d458b4 BufferingStreamSubscription._sendData + 196 (stream_impl.dart:366)
18  App                           	0x0000000112d1f34c BufferingStreamSubscription._add (#3) + 136 (stream_impl.dart:297)
19  App                           	0x0000000112d1f24c _SyncStreamControllerDispatch._sendData + 24 (stream_controller.dart:777)
20  App                           	0x0000000112d1f24c StreamController._add (#3) + 188 (stream_controller.dart:651)
21  App                           	0x00000001125ffaa0 StreamController.add (#3) + 104 (stream_controller.dart:606)
22  App                           	0x0000000112579dd0 StreamController.add (#2) + 36
23  App                           	0x0000000112f31110 Closure.call (#2) + 704 (function.dart:0)
24  App                           	0x00000001125ee914 RawReceivePort._handleMessage + 184 (isolate_patch.dart:184)
25  App                           	0x000000011254fb8c stub InvokeDartCode + 216
26  Flutter                       	0x0000000106c7804c dart::InvokeDartCode(unsigned long, dart::Array const&, dart::Array const&, dart::Thread*) + 328 (dart_entry.cc:106)
27  Flutter                       	0x0000000106c7804c dart::DartEntry::InvokeFunction(dart::Function const&, dart::Array const&, dart::Array const&) + 384 (dart_entry.cc:149)
28  Flutter                       	0x0000000106c83d8c dart::DartEntry::InvokeFunction(dart::Function const&, dart::Array const&) + 76 (dart_entry.cc:38)
29  Flutter                       	0x0000000106c83d8c dart::DartLibraryCalls::HandleMessage(long long, dart::Instance const&) + 168 (dart_entry.cc:718)
30  Flutter                       	0x0000000106c83d8c dart::IsolateMessageHandler::HandleMessage(std::_fl::unique_ptr<dart::Message, std::_fl::default_delete<dart::Message>>) + 2772 (isolate.cc:1456)
31  Flutter                       	0x0000000106c88d04 dart::MessageHandler::HandleMessages(dart::MonitorLocker*, bool, bool) + 324 (message_handler.cc:229)
32  Flutter                       	0x0000000106c88b4c dart::MessageHandler::TaskCallback() + 116 (message_handler.cc:443)
33  Flutter                       	0x0000000106c88b4c dart::MessageHandlerTask::Run() + 140 (message_handler.cc:31)
34  Flutter                       	0x0000000106d222ec dart::ThreadPool::WorkerLoop(dart::ThreadPool::Worker*) + 168 (thread_pool.cc:203)
35  Flutter                       	0x0000000106d222ec dart::ThreadPool::Worker::Main(unsigned long) + 376 (thread_pool.cc:363)
36  Flutter                       	0x0000000106ce590c dart::ThreadStart(void*) + 312 (os_thread_macos.cc:94)
37  libsystem_pthread.dylib       	0x0000000227bc27d0 _pthread_start + 136 (pthread.c:931)
38  libsystem_pthread.dylib       	0x0000000227bc2480 thread_start + 8 (:-1)
@GabrielAraujo GabrielAraujo added the bug Something isn't working label Apr 25, 2025
@greenrobot-team
Copy link
Member

greenrobot-team commented Apr 28, 2025

Thanks for reporting.

As I noted in the other issue, the symbolicated stack trace is likely not correct for the ObjectBox lines.

First, I recommend to make sure that your project can upgrade to the latest ObjectBox Dart packages (yours appears to be stuck on 4.0.3, the latest available version is 4.2.0, dart pub updated could help) and ObjectBox Pod. And also using the latest Flutter SDK (and therefore the latest Dart SDK) may help.

But thanks for sharing the crash log, at least we now know this is happening during building a query.

Do you see any pattern on which devices are affected, like model, iOS version?

Edit: for our reference, this is internal issue objectbox-dart#146

@greenrobot-team greenrobot-team self-assigned this Apr 28, 2025
@GabrielAraujo
Copy link
Author

Mostly iPhones

Testflight
Image

Production
Image

Another quick note is that we have other similar entities such as TemplateItem and TemplateComment where we do similar querying hasSynced but it seems like it is only affecting the TemplateSection entity

@greenrobot-team
Copy link
Member

greenrobot-team commented Apr 29, 2025

@GabrielAraujo Thanks! In that case, can you share more about where the query builder code is used (maybe also compared to the other entities)? The log shows StreamController and hints at the use of isolates?

There have been similar issues to this which I think are rooted in the fact that the ObjectBox database is a native component that exists outside of all Dart isolates. Somehow the database gets closed, then causing a crash when trying to use it from Dart.

@GabrielAraujo
Copy link
Author

So those queries run every 30 seconds or so to fetch locally models that haven't synced yet to the remote servers. Once the changes sync we update the models locally setting this hasSynced attribute to true.
We've recently ported most of our sync operations with lists and async operations from ObjectBox to sync ones inside a single isolate worker. The same store is used on the main isolate and on this background isolate worker.

This isolate is spawned at app startup and only closes when app is closed.

Not related Note: We've done this migration because we were having some overhead with isolate spawn when using async objectbox operations directly and in some use cases using the sync one with large lists were causing UI jank.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants