Skip to content

fix(ndk): Create outbox directory before writing crash envelopes#1889

Merged
runningcode merged 3 commits into
masterfrom
no/ndk-create-outbox-dir-before-write
Jul 22, 2026
Merged

fix(ndk): Create outbox directory before writing crash envelopes#1889
runningcode merged 3 commits into
masterfrom
no/ndk-create-outbox-dir-before-write

Conversation

@runningcode

Copy link
Copy Markdown
Contributor

Summary

On Android, the NDK layer writes crash/native envelopes through a custom transport (send_envelope in ndk/lib/src/main/jni/sentry.c) that targets the head SDK's outbox path. However:

  • Native sentry_init only creates its own database directory, which the JNI layer derives as .sentry-native — a sibling of the outbox, not the outbox itself (sentry.c:417-429).
  • The transport writes the envelope with sentry_envelope_write_to_file, which ultimately open(..., O_CREAT)s the file but does not create parent directories.

So if the outbox directory does not exist when an envelope is flushed, the write fails silently (only a SENTRY_WARN) and the crash report is lost. Today this works only because head SDKs (and the sample's MainActivity.setupOutboxFolder()) create the outbox eagerly.

This becomes a real risk as head SDKs move to lazy outbox/cache creation (e.g. getsentry/sentry-java#5792): a native envelope written before the head SDK's lazy creator runs would be dropped.

Change

Create the outbox directory in the transport before each write, using sentry__path_create_dir_all — the same recursive, self-healing pattern every other sentry-native write path (cache, external) already uses. This makes native self-sufficient and lets head SDKs defer outbox creation without dropping native crash envelopes.

Notes

  • The internal sentry__path_* symbols are exported via the sentry_* glob in src/exports.map and are already reached from this JNI file via extern (e.g. sentry__value_from_json, sentry__backend_preload), so this follows the established pattern.

🤖 Generated with Claude Code

@runningcode
runningcode marked this pull request as ready for review July 21, 2026 08:56
Comment thread ndk/lib/src/main/jni/sentry.c
@runningcode
runningcode force-pushed the no/ndk-create-outbox-dir-before-write branch from 44e2e29 to 8372d2a Compare July 21, 2026 09:17
Comment thread ndk/lib/src/main/jni/sentry.c Outdated
@runningcode
runningcode force-pushed the no/ndk-create-outbox-dir-before-write branch from 374e9c0 to 5b135bb Compare July 21, 2026 09:26
runningcode and others added 2 commits July 21, 2026 11:33
The NDK layer writes crash envelopes through a custom transport that
targets the head SDK's outbox path. Native init only creates its own
`.sentry-native` database directory (a sibling of the outbox), and the
envelope write does not create parent directories, so a missing outbox
made the write fail silently and the crash report was lost.

Create the outbox in the transport before each write, matching how the
rest of sentry-native ensures its cache and external directories exist,
and log if creation fails so the failure is diagnosable. This lets head
SDKs create the outbox lazily without dropping native crash envelopes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
sentry-native now creates the outbox directory itself before writing,
so the sample no longer needs to create it up front.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@runningcode
runningcode force-pushed the no/ndk-create-outbox-dir-before-write branch from 5b135bb to 725e730 Compare July 21, 2026 09:34
Comment thread ndk/lib/src/main/jni/sentry.c Outdated
@codecov

codecov Bot commented Jul 21, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 75.75%. Comparing base (8ef6876) to head (f212c73).
⚠️ Report is 3 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1889      +/-   ##
==========================================
+ Coverage   75.42%   75.75%   +0.32%     
==========================================
  Files          92       92              
  Lines       21599    21966     +367     
  Branches     3807     3914     +107     
==========================================
+ Hits        16291    16640     +349     
- Misses       4438     4442       +4     
- Partials      870      884      +14     
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

The previous approach called sentry__path_* and sentry__logger_log via
extern declarations. Those symbols are internal to the core library and,
unlike SENTRY_API-tagged ones, are not exported from the shared object the
NDK links against, so the Android build failed to link with undefined
symbol errors.

Create the outbox directory directly with mkdir(2) instead. The NDK
library is Android-only, so POSIX is always available, and log failures
through __android_log_print rather than the unexported core logger.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@runningcode
runningcode merged commit bc464d3 into master Jul 22, 2026
67 checks passed
@runningcode
runningcode deleted the no/ndk-create-outbox-dir-before-write branch July 22, 2026 13:17
Comment on lines +314 to +316
// sentry-native's path helpers are internal to the core library and not
// exported from the shared object we link against, so we create the outbox
// ourselves. Android is always POSIX, so mkdir(2) is all we need.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry about this, btw. it's not that easy to access sentry-native internals. 🙂 we probably don't want to expose sentry_path at this point, unfortunately...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants