Repository navigation
feat: error reporting (crashes and handled errors) - #38
Merged
Merged
Conversation
cristipufu
force-pushed
the
feat/error-reporting
branch
3 times, most recently
from
October 16, 2026 12:47
68c9f1b to
1387ba6
Compare
5 tasks done
Reports errors to the error endpoint (/api/v0/error), the same way the React
Native, MAUI, Unity and Unreal SDKs do; they appear on the Errors page.
- Handled errors: `ErrorTracker` on App/AppHandle/Window (`track_error(&err)`
for any std::error::Error, with its type name and causes;
`track_error_report(ErrorReport)` for full control, `with_fatal(true)` for
severity fatal), and `trackError(error, { fatal })` in the JS bindings
behind the new `aptabase:allow-track-error` permission.
- Crashes: `Builder::with_crash_reporting()`. A panic in a spawned task is a
`taskException` on whatever thread it runs (only the task dies; a
single-thread runtime runs its tasks on the main thread); otherwise a panic
on the main thread is a fatal `crash`, and one on another thread is
`unhandled`. An init script reports the webview's uncaught errors
(`unhandled`) and unhandled rejections (`taskException`), skipping "Script
error." and ResizeObserver loop noise. A custom `with_panic_hook` still runs
first; what it tracked is flushed after the crash's report, within the same
limit.
- A crash's report goes straight out, never through the queue: from a thread
and a runtime of its own, on a connection of its own, without waiting for a
send in flight (which may be stuck on the very runtime the crashing thread
is on, e.g. a single-thread runtime handed to Tauri with
`tauri::async_runtime::set`), and even with the queue full. The reports
queued before it follow; the hook waits at most 3 s in all.
- Delivery: one report per request, sent right away; fields cut to the
endpoint's limits in UTF-16 units (as .NET counts them, so a report is never
refused for length); never an empty type or message; network errors, 408,
429 and 5xx retried in order, 403 (quota) and other 4xx dropped; at most 25
queued, a fatal report taking the place of the oldest one that isn't.
- Tokio's `rt`, `time` and `net` features are declared rather than relied on
through Tauri's (`tokio::time::sleep` was already used without `time`).
Fix: `flush_events_blocking()` (and the flush after a custom panic hook)
panicked with "there is no reactor running" when events were queued and the
thread was outside the async runtime, e.g. the main thread handling
RunEvent::Exit as the README shows. Outside the runtime the flush now runs on
it while the thread waits; inside one it runs in place, as before.
Tests: report fields and limits, retry rules, the queue cap and its fatal
eviction, a crash sent first with the queue full and without waiting for a
flush in progress, a blocking flush from outside the runtime (fails on the old
code), and end to end through a mock Tauri app: panics reported as what they
ended, a crash on the only thread of a single-thread runtime delivered while
another report's send is stuck in flight (lost before, and the task's panic
misreported as a crash), and the webview's track_error arguments over IPC.
Release 1.3.0 (crate) and 0.7.0 (@aptabase/tauri on npm).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
cristipufu
force-pushed
the
feat/error-reporting
branch
from
October 16, 2026 13:53
1387ba6 to
72e612e
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds error reporting to the error endpoint (
/api/v0/error), matching the React Native, MAUI, Unity and Unreal SDKs. Reports appear on the Errors page of the dashboard.Handled errors (try/catch)
Rust, through a new
ErrorTrackertrait onApp,AppHandleandWindow:JavaScript, behind the new
aptabase:allow-track-errorpermission:Crashes
fatal/crasherror/taskExceptionerror/unhandlederror/unhandlederror/taskExceptionA hook set with
with_panic_hookstill runs first. Withpanic = "abort", every panic is a crash.A crash's report goes straight out, never through the queue. It is sent from a thread and a runtime of its own, on a connection of its own, so it doesn't wait for a send already in flight, which may be stuck on the crashing runtime: an app can hand Tauri a single-thread runtime with
tauri::async_runtime::set. A full queue can't drop it either. The reports queued before it follow, and the hook waits at most 3 s in all. What a customwith_panic_hooktracked is flushed after the crash's report, within the same limit.Delivery
Fix included
flush_events_blocking(), and the flush after a custom panic hook, panicked withthere is no reactor runningwhen events were queued and the calling thread was outside the async runtime. That includes the main thread handlingRunEvent::Exit, which is the pattern the README shows. From such a thread the flush now runs on Tauri's runtime while the thread waits; inside a runtime it runs in place, as before. The crash path needed this, and it fixes the exit flush too.Tests
The crate had no tests before; it now has 21, run with
cargo test. Among the unit tests: a crash sent first with the queue full, a crash that doesn't wait for a flush in progress, and a fatal report evicting the oldest non-fatal one.tests/crash_reporting.rs: the plugin built into a mock Tauri app. A panic on a thread namedmainarrives as a fatal crash before the hook returns, and a panic in atauri::async_runtimetask arrives as ataskException.tests/crash_on_single_thread_runtime.rs: a crash on the only thread of a single-thread runtime handed to Tauri, while another report's send is stuck in flight, is delivered at once. The task panic before it is reported as ataskException, not as a crash.tests/ipc.rs: the webview'strack_errorarguments as JavaScript names them (errorType,stackTrace: null,kind), through Tauri's IPC.The example app turns on crash reporting and adds two buttons, Report an error and Panic in Rust.
Tokio's
rt,timeandnetfeatures are now declared rather than relied on through Tauri's:tokio::time::sleepwas already used withouttime.No version bump: the changelog has an
[Unreleased]entry.Release
This PR also releases 1.3.0 (crate) and 0.7.0 (
@aptabase/taurion npm):Cargo.tomlandpackage.jsonare bumped, the changelog section is[1.3.0] - 2026-10-16(it includes #40), and the install snippets in the README and llms.txt point at 1.3. Publishing a1.3.0GitHub release after merging runsrelease.ymlfor both registries.cargo publish --dry-runandnpm pack --dry-runpass locally, and the committedwebview-distmatches a fresh build.🤖 Generated with Claude Code