Skip to content

Commit 2dfe4e1

Browse files
runningcodeclaude
andcommitted
fix(core): Create the cache dir before writing app-start config (JAVA-613)
The removed init-time mkdirs() ran on the dsn-hashed cache path and created the un-hashed parent as a side effect. handleAppStartProfilingConfig writes app_start_profiling_config into that parent via createNewFile(), which fails with IOException when the parent is missing, and the surrounding catch swallows it into a log line. The next launch then finds no config and cannot start app-start profiling. This was masked because the profiling traces dir still calls mkdirs() on <cacheDir>/<dsnHash>/profiling_traces, creating the un-hashed grandparent -- but only when profiling is enabled, which every existing test did. The new test leaves profiling off so nothing else materializes the dir. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 6b422c3 commit 2dfe4e1

2 files changed

Lines changed: 23 additions & 1 deletion

File tree

sentry/src/main/java/io/sentry/Sentry.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import io.sentry.util.DebugMetaPropertiesApplier;
2525
import io.sentry.util.FileUtils;
2626
import io.sentry.util.InitUtil;
27+
import io.sentry.util.LazyDirectory;
2728
import io.sentry.util.LoadClass;
2829
import io.sentry.util.Platform;
2930
import io.sentry.util.SentryRandom;
@@ -463,8 +464,9 @@ private static void handleAppStartProfilingConfig(
463464
() -> {
464465
final String cacheDirPath = options.getCacheDirPathWithoutDsn();
465466
if (cacheDirPath != null) {
467+
final @NotNull LazyDirectory cacheDir = new LazyDirectory(cacheDirPath);
466468
final @NotNull File appStartProfilingConfigFile =
467-
new File(cacheDirPath, APP_START_PROFILING_CONFIG_FILE_NAME);
469+
new File(cacheDir.getFile(), APP_START_PROFILING_CONFIG_FILE_NAME);
468470
try {
469471
// We always delete the config file for app start profiling
470472
FileUtils.deleteRecursively(appStartProfilingConfigFile);
@@ -481,6 +483,9 @@ private static void handleAppStartProfilingConfig(
481483
"Tracing is disabled and app start profiling will not start.");
482484
return;
483485
}
486+
// The cache dir is no longer created during init, so materialize it here before
487+
// writing: createNewFile() fails if the parent is missing.
488+
cacheDir.getOrCreate();
484489
if (appStartProfilingConfigFile.createNewFile()) {
485490
// If old app start profiling is false, it means the transaction will not be
486491
// sampled, but we create the file anyway to allow continuous profiling on app

sentry/src/test/java/io/sentry/SentryTest.kt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1316,6 +1316,23 @@ class SentryTest {
13161316
assertTrue(appStartProfilingConfigFile.exists())
13171317
}
13181318

1319+
@Test
1320+
fun `init creates app start profiling config when the cache dir does not exist yet`() {
1321+
val path = getTempPath()
1322+
// Profiling is left disabled on purpose: it is the only other init-time consumer that creates
1323+
// the cache dir, so with it off nothing materializes the dir before the config is written.
1324+
initForTest {
1325+
it.dsn = dsn
1326+
it.cacheDirPath = path
1327+
it.isEnableAppStartProfiling = false
1328+
it.isStartProfilerOnAppStart = true
1329+
it.tracesSampleRate = 0.0
1330+
it.profilesSampleRate = null
1331+
it.executorService = ImmediateExecutorService()
1332+
}
1333+
assertTrue(File(path, "app_start_profiling_config").exists())
1334+
}
1335+
13191336
@Test
13201337
fun `init saves SentryAppStartProfilingOptions to disk`() {
13211338
var options = SentryOptions()

0 commit comments

Comments
 (0)