Debug Symbols and Obfuscation
By default, the tk-ota-push CLI compiles all Releases and Patches with Dart obfuscation enabled (--obfuscate) and generates split DWARF symbol tables (--split-debug-info). These .symbols files are automatically uploaded and sealed per architecture inside the OTA server's Artifact signing engine so you can deobfuscate production crash stack traces at any time using tk-ota-push symbols.
1. Automatic Generation and Archiving During Builds (release & patch)
Related CLI Options (addCommonOptions)
| Option / Flag | Default | Behavior in Publisher |
|---|---|---|
--obfuscate | true | Passes --obfuscate and --split-debug-info=<symDir> to flutter build. |
--no-obfuscate | — | Disables obfuscation (unless --split-debug-info is explicitly provided). |
--split-debug-info <dir> | build/ota_symbols/<version> | Customizes the local directory where Flutter writes .symbols files. |
Per-Platform and Per-Architecture Resolution (Publisher.resolveSymbolsFile)
Inside build/ota_symbols/<version> (or the custom --split-debug-info directory), the CLI searches in order for:
- Android 64-bit (
aarch64):app.android-arm64.symbols - Android 32-bit (
arm):app.android-arm.symbols - iOS (
aarch64):app.ios-arm64.symbols - Generic pattern:
app.<platform>-<arch>.symbols(falling back to the first*.symbolsfile found).
iOS Linker Specifics (patchIos)
When building an iOS patch, flutter build ios --release --no-codesign produces the app.dill kernel, and then gen_snapshot_arm64 and aot-tools.dill link assemble the final snapshot. When obfuscation is active, the CLI explicitly passes the following 4 DWARF flags to both gen_snapshot_arm64 and aot_tools link (after --):
--dwarf-stack-traces
--resolve-dwarf-paths
--save-debugging-info=<symDir>/patch_<version>.symbols
--strip
This guarantees that the patch artifact snapshot and the base binary share identical DWARF stack conventions and prevents dwarf_stack_traces vs no-dwarf_stack_traces linker errors.
Multipart Upload to the Server
In OtaApiClient._multipart, if symbolsFile exists on disk, it is attached under the symbols_file multipart field during POST /api/admin/v1/releases and POST /api/admin/v1/patches. The server computes its symbolsSha256Hash digest and prints it in the CLI receipt:
│ Symboles (.symbols) : Archivés (app.android-arm64.symbols • SHA-256 : 998877665544...)
2. Downloading Patch Symbols (tk-ota-push symbols)
When an obfuscated stack trace is reported from a production device, run the symbols subcommand to download the exact .symbols file bound to the patch UUID:
tk-ota-push symbols --patch-id <uuid> [-o <output_path>] [options]
tk-ota-push symbols Options
| Option | Abbr. | Mandatory | Default | Description |
|---|---|---|---|---|
--patch-id | — | Yes | — | UUID of the patch whose .symbols file should be downloaded. |
--output | -o | No | patch_<patchId>.symbols | Local destination path for the downloaded .symbols file. |
--tenant-id | — | No | shorebird.yaml / session / default | Tenant identifier. |
--server | — | No | shorebird.yaml / env / http://localhost:8080 | OTA server URL. |
--project | — | No | . | Flutter project path (to read shorebird.yaml). |
Complete Local Deobfuscation Example (flutter symbolize)
# 1. Download the patch .symbols file
tk-ota-push symbols \
--patch-id 8b73f831-29cf-4cb6-8801-44ebda29910a \
-o build/crash_triage/patch_1.symbols
CLI output:
Téléchargement du fichier .symbols pour le patch 8b73f831-29cf-4cb6-8801-44ebda29910a...
✅ Fichier .symbols enregistré dans : build/crash_triage/patch_1.symbols (418204 octets)
Pour dé-obfusquer une stacktrace : flutter symbolize -i crash.txt -d build/crash_triage/patch_1.symbols
# 2. Deobfuscate the stack trace using the standard Flutter tool
flutter symbolize -i crash.txt -d build/crash_triage/patch_1.symbols
3. Downloading Release Symbols or Server-Side Deobfuscation
In addition to tk-ota-push symbols, OtaApiClient and OtaAdminController expose two additional endpoints:
- Download the base
.symbolsof a Release (OtaApiClient.downloadReleaseSymbols):curl -L "$OTA_SERVER_URL/api/admin/v1/releases/$RELEASE_ID/symbols" \
-H "Authorization: Bearer $OTA_API_KEY" \
-o release_base.symbols - Deobfuscate a stack trace directly via the REST API:
curl -X POST "$OTA_SERVER_URL/api/admin/v1/patches/$PATCH_ID/deobfuscate" \
-H "Authorization: Bearer $OTA_API_KEY" \
--data-urlencode "stacktrace@crash.txt"