objectbox-dart
objectbox-dart copied to clipboard
Impossible to update data on FCM Background Message : object put failed: 10002 ID is higher or equal to internal ID sequence
Hello,
Using objectbox: 1.3.0
I am having a problem trying to update data when I receive a notification from FCM when the application is running in the background.
When a notification comes from FCM, the code successfully retrieves the corresponding data from the ObjectBox database. But when the code tries to update this data, it throws an exception
Invalid argument(s): object put failed: 10002 ID is higher or equal to internal ID sequence: 31 (vs. 31). Use ID 0 (zero) to insert new entities.
Out of 10 attempts 3 fail.
Entity code
@Entity()
@JsonSerializable()
class Requirements implements BaseEntity {
@Id()
int localId;
@Unique()
String? id;
String? description;
}
Firebase Messaging Background Handler
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
await _initObjectBox();
Store store = SketchPage.store!;
switch (notification.type) {
case TypeNotification.REQUIREMENT_RESPONSE:
case TypeNotification.REQUIREMENT_CANCEL:
Requirements requirements = await WebService.getNeedsExpressionService()
.getRequirementsById(notification.objectId!);
RequirementsDao requirementsDao = RequirementsDao(store);
bool result = requirementsDao.updateRequirementsStatus(requirements);
break;
}
Update Requirement Function
bool updateRequirementsStatus(Requirements data) {
final Box<Requirements> requirementsBox = store.box<Requirements>();
Query<Requirements> query = requirementsBox.query(Requirements_.id.equals(data.id!)).build();
Requirements? requirements = query.findFirst();
if (requirements == null) return false;
requirements.status = data.status;
int id = requirementsBox.put(requirements); // fail here
return id == requirements.localId;
}
Thank you for helping me.
object put failed: 10002 ID is higher or equal to internal ID sequence
This message indicates that your code is trying to put an object with an ID that has not been assigned, yet. By default, new objects have to be put with ID = 0 (in your case localId) so ObjectBox will assign the next available ID to them. So make sure that it's set to 0, or only to an already assigned ID.
Alternatively, though not recommended, you can change this behavior to let your code assign IDs: https://docs.objectbox.io/advanced/object-ids#self-assigned-object-ids
@greenrobot-team The error occurs when the application is running in the background and FCM fires. Instead, I'm trying to update an existing data when a notification arrives. When I do a fetch, I retrieve the existing data from the database and when I try to update it, it generates the error. And when it starts and the application receives another notification, it generates an error also related to the ID. But when I restart the application again, it no longer throws an error, even I quit afterwards.
@madrojudi Did you read my comment? If your code wants to update an existing object, it needs to use an existing localId. The error message indicates that your code uses a localId that is not in use by any existing object.
@greenrobot-team I understood what you said. But it's not me who puts the localId. Looks more like Objectbox doesn't update all the time between differents FlutterEngine.
I explain in more detail.
- The application runs in the background and receives a notification, this notification indicates that the status of the data, for the
id=acedc-125553-fca2233, has changed, it is an example - I run a query to get corresponding data from Objectbox :
{
localId: 31,
id: acedc-125553-fca2233,
status: PENDING,
name: Example
}
- Now I just changed the status value, to IN_PROGRESS for example.
localId: 31,
id: acedc-125553-fca2233,
status: IN_PROGRESS,
name: Example
}
- I run the query to put the update data, and it generates the error
Invalid argument(s): object put failed: 10002 ID is higher or equal to internal ID sequence: 31 (vs. 31). Use ID 0 (zero) to insert new entities.
This is when FCM run on background. It happens, but not all the time. This often happens in the following cases but not all the time :
- the user switches to another application without closing my app
- the user makes HOME without closing the application
- the phone (Android) goes to sleep while the application is in the foreground.
Thanks for the clarification. Maybe this can be solved by using Store.attach to attach to the store that is already open for your app?
See my comment at https://github.com/objectbox/objectbox-dart/issues/436#issuecomment-1168484708 on a similar issue about using multiple Flutter Engines.
Unfortunately it doesn't always work for me. But I found an alternative that is currently working.
- I check if DB is open with
Store.isOpen(path). If it is true, I useStore.attach - If
Store.isOpenis false, I try to open new Store byopenStore. When it open, I save the reference into a file - If
Store.isOpenthrow error, I check to read the reference which I save in2.and I useStore.fromReferenceto open Store
Currently, It is working. I will continue testing to see if it is stable.
Unfortunately it doesn't always work for me. But I found an alternative that is currently working.
- I check if DB is open with
Store.isOpen(path). If it is true, I useStore.attach- If
Store.isOpenis false, I try to open new Store byopenStore. When it open, I save the reference into a file- If
Store.isOpenthrow error, I check to read the reference which I save in2.and I useStore.fromReferenceto open StoreCurrently, It is working. I will continue testing to see if it is stable.
Hello! This solved my problem.