-
Notifications
You must be signed in to change notification settings - Fork 33
Description
Suggested Documentation Improvement
The Problem
Calling await BackgroundRunner.dispatchEvent() can hang indefinitely without throwing an error if the details payload contains a non-plain JavaScript object (POJO). The await never resolves, and the event is never received by the background task, making it very difficult to debug.
This commonly occurs when passing data directly from other Capacitor plugins, such as the GeolocationPosition object from @capacitor/geolocation, which I believe is a class instance, not a plain object. Even though the object looks serializable when logged to the console, it causes the native bridge to fail silently.
A reliable workaround is to sanitize the data before dispatching, for example, by using JSON.parse(JSON.stringify(data)).
How to Reproduce
Set up a listener for an event in the background runner.
In the frontend, get the user's location using @capacitor/geolocation.
Call dispatchEvent and pass the entire position object returned from the geolocation plugin in the details payload.
Observe that the code execution stops at the await and the background task does not log the event.
Code Example
// This code will cause the dispatchEvent call to hang
import { Geolocation } from '@capacitor/geolocation';
import { BackgroundRunner } from 'capacitor-background-runner';
async function dispatchLocationUpdate() {
// The 'position' object is an instance of GeolocationPosition, not a plain object.
const position = await Geolocation.getCurrentPosition();
console.log('Attempting to dispatch event...');
await BackgroundRunner.dispatchEvent({
label: 'com.example.app.locationUpdate',
event: 'locationUpdated',
details: {
locationData: position // This is the problematic part
}
});
// This line is never reached
console.log('Event dispatched successfully!');
}
Suggested Solution
It may be worth updating the documentation for BackgroundRunner.dispatchEvent to include a warning or a note about this behavior. The documentation should explicitly state that the details object must be a plain, JSON-serializable object and not a class instance. The type is [key: string]: any at the moment, so maybe some details about this here in the docs under description of the details
key?

Quick fix:
For anyone finding this issue, try to JSON.parse(JSON.stringify(details))
This method is easy, available and deep-clones the object, stripping any class information.
const position = await Geolocation.getCurrentPosition();
console.log('Attempting to dispatch event...');
await BackgroundRunner.dispatchEvent({
label: 'com.example.app.locationUpdate',
event: 'locationUpdated',
details: {
locationData: JSON.parse(JSON.stringify(position)) // This is the fix
}
});
Adding this to the documentation would save developers significant time and confusion. I'd be happy to submit a PR for the documentation change if that would be helpful, and if you could point me in the right direction of the file to change.
My Environment
Capacitor Version: 7.x
capacitor-background-runner Version: ^2.1.0
Platform(s): iOS / Android