Skip to content

Docs: dispatchEvent fails silently with non-POJO data #131

@JamieCurnow

Description

@JamieCurnow

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?

Image

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions