Error Tracking
Capture errors and crashes in your game with automatic stack traces. The SDK also includes a Flight Recorder that captures 60 seconds of telemetry data before each error, helping you understand what led to the crash.
Automatic Error Capture (since SDK v1.4.0)
Section titled “Automatic Error Capture (since SDK v1.4.0)”The SDK hooks into Godot’s logging system via OS.add_logger() and forwards every runtime error to the dashboard automatically — no track_error() call needed in your game code. This catches engine-level errors that GDScript can’t catch with try/except patterns: null dereferences, missing methods, signal mismatches, shader errors, etc.
Requirements:
- Godot 4.5 or newer (Logger class must be exposed to GDScript)
- The Project Setting
quest_data/auto_capture_errorsmust betrue(default)
What gets captured:
- All
ERROR_TYPE_ERROR,ERROR_TYPE_SCRIPT, andERROR_TYPE_SHADERevents - Function name, source file, line number, error code, rationale message
- Full multi-language script backtrace (
Array[ScriptBacktrace]— GDScript + C# frames if Mono build) - OS, game version, dedup hash for crash-grouping
What is intentionally NOT captured:
WARNING:andSCRIPT WARNING:(too noisy, rarely actionable)- Errors originating from inside the SDK itself (
addons/quest_data/...) — feedback-loop guard
Dedup behavior: the same file:line:function signature fires at most once per 30 seconds. If your hover handler crashes 60 times per second, the dashboard sees one event per 30s window — no spam.
Opt-out
Section titled “Opt-out”If you don’t want auto-capture (e.g. you want to manually decide what to ship to the backend):
# project.godot[quest_data]auto_capture_errors=falseOr via Project Settings UI: Project > Project Settings > Quest Data > Auto Capture Errors. You can still call QuestData.track_error() manually for caught exceptions even with auto-capture off.
Functions
Section titled “Functions”track_error()
Section titled “track_error()”QuestData.track_error(error_name: String, error_msg: String = "")| Parameter | Type | Default | Description |
|---|---|---|---|
error_name | String | required | Error type identifier (e.g. "NullReference", "SaveCorrupted") |
error_msg | String | "" | Human-readable error message |
Sends an error_occurred event with:
- Full GDScript stack trace
- Stack snippet (short version for quick scanning)
- Operating system info
- Game version (from
application/config/versionin ProjectSettings) - Flight Recorder data (last 60 seconds of FPS, memory, events)
Example
Section titled “Example”# Track a caught errorfunc load_save_file(path: String) -> Dictionary: var file = FileAccess.open(path, FileAccess.READ) if file == null: QuestData.track_error("SaveLoadFailed", "Could not open: " + path) return {}
var data = file.get_var() if not data is Dictionary: QuestData.track_error("SaveCorrupted", "Expected Dictionary, got " + type_string(typeof(data))) return {}
return data
# Track unexpected statesfunc apply_damage(amount: int): if amount < 0: QuestData.track_error("InvalidDamage", "Negative damage: " + str(amount)) return health -= amountWrapping Risky Operations
Section titled “Wrapping Risky Operations”func parse_server_response(json_string: String) -> Dictionary: var json = JSON.new() var error = json.parse(json_string) if error != OK: QuestData.track_error("JSONParseError", json.get_error_message()) return {} return json.get_data()Flight Recorder
Section titled “Flight Recorder”The SDK continuously captures telemetry snapshots every second, keeping the last 60 seconds in a circular buffer. When track_error() is called, this data is attached to the error event.
Each snapshot includes:
- FPS at that moment
- Memory usage (MB)
- Active scene name
- Recent events tracked in that second
This lets you see what happened before the crash — was the game running low on memory? Did FPS drop? What events fired right before?
Dashboard View
Section titled “Dashboard View”In the dashboard under Analytics > Dashboard, the error detail view shows:
- Error grouping — Same errors are grouped by
error_name - Occurrence count — How often this error happens
- Stack trace — Full and snippet views
- Flight Recorder charts — FPS and memory graphs for the 60 seconds before the crash
How It Works
Section titled “How It Works”track_error()captures the current GDScript call stack viaget_stack()- The stack is formatted into a readable string and a short snippet
- Flight Recorder data (last 60 snapshots) is serialized and attached
- The event is queued like any other event (batched, offline-safe)
Best Practices
Section titled “Best Practices”- Use descriptive error names —
"SaveCorrupted"is better than"Error" - Include context in the message — File paths, expected vs. actual values, player state
- Don’t track expected failures — A player losing a level is not an error
- Track at boundaries — File I/O, network responses, JSON parsing, scene transitions
- Keep error names consistent — Same error type should always use the same
error_namefor grouping