Skip to content
NativeWatch

Offline delivery and the event outbox

Understand NativeWatch's bounded local outbox, retry and rejection behavior, delivery receipts, and device checks for offline reporting.

By NativeWatch Updated

The SDK normally writes a captured event to a local outbox, then attempts delivery after a response or queue job. This lets temporary network failures leave work for a later flush. It is a bounded queue, so it cannot guarantee delivery of every event.

Follow an event through delivery

A PHP event enters storage/nativewatch/outbox by default. The SDK flushes up to 10 reports during its normal lifecycle hook. Native crash evidence takes an extra step: the native collector writes a report, then PHP imports it after the app relaunches.

The default outbox holds at most 100 events and drops the oldest when it exceeds that limit. It processes stored events oldest first and stops at the first temporary delivery failure. Native crash storage is separately bounded. Uninstalling the app, clearing storage, withdrawing consent or exceeding a queue limit can remove pending reports.

Capture and file operations still have a cost. If the outbox cannot be written, capture can attempt immediate network delivery. Give the installed app a writable persistent storage directory and test its actual configuration.

Interpret transport results

Result Queue behavior
Successful HTTP response Accepted event leaves the outbox
Network error or server 5xx Event stays for a later flush
Throttling 429 Event stays; Retry-After, when supplied, is persisted
Quota 429 with event_quota_exceeded Permanent rejection; event leaves the outbox
Other permanent 4xx Rejected event leaves the outbox
Unreadable stored payload Removed and counted separately

The receiver deduplicates accepted retries by project and event UUID, avoiding an additional quota charge or ingestion job for the same accepted event. API acceptance still precedes background processing and storage in the dashboard.

Inspect pending work

From the app's configured PHP environment, run:

php artisan nativewatch:flush

The command prints accepted, rejected, unreadable and remaining counts. It returns a nonzero exit status if reporting is disabled, reports were rejected or unreadable, a delivery failed, or work remains. A desktop terminal may not use the installed app's storage directory, and it cannot inspect native crash files on your phone.

For a deliberate development diagnostic in code:

use ZXN\NativeWatch\Core\Laravel\NativeWatch;
use ZXN\NativeWatch\Core\Transport\SendResult;

$id = NativeWatch::captureMessage('Delivery verification');
$report = NativeWatch::flushReport();
$accepted = $id !== null
    && NativeWatch::deliveryResult($id) === SendResult::Sent;
$remaining = NativeWatch::pending();

flushReport() separates accepted, rejected, unreadable, failed and remaining counts. flush() returns the number of removed files, which includes rejections. Do not interpret removal as acceptance. Per-event receipts cover the latest 64 event IDs in the current client process and are not durable acknowledgements from the dashboard.

Verify offline behavior on a device

Use a dedicated Release build and project. Grant diagnostics while online, enable airplane mode and verify Wi-Fi is off too. Capture a real test exception, record its UUID and pending count, and relaunch while still offline. The event should remain local.

Restore connectivity, reopen the app and allow normal delivery. Match that same UUID to the received occurrence, then check that pending work cleared. Repeat with a native crash followed by relaunch, and repeat offline capture followed by consent withdrawal. Earlier reports must not arrive after a later grant.

Physical-iPhone flight-mode acceptance remains deferred in the current project evidence. Automated network tests, browser checks and simulator runs verify different things. Record your device, OS, build, UUID and observed result separately.

If delivery remains blocked, check the destination, ingest key, consent, quota response and retry deadline before capturing more events.