{"record":{"id":"49b46c9c0513bfff","repo":"didi/DoKit","slug":"cannot-set-the-leakdirectoryprovider-after-it-has","errorCode":null,"errorMessage":"Cannot set the LeakDirectoryProvider after it has already been set. Try setting it before installing the RefWatcher.","messagePattern":"Cannot set the LeakDirectoryProvider after it has already been set\\. Try setting it before installing the RefWatcher\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"Android/dokit-leakcanary/src/main/java/com/squareup/leakcanary/internal/LeakCanaryInternals.java","lineNumber":198,"sourceCode":"        notificationManager.createNotificationChannel(notificationChannel);\n      }\n      builder.setChannelId(NOTIFICATION_CHANNEL_ID);\n    }\n\n    if (SDK_INT < JELLY_BEAN) {\n      return builder.getNotification();\n    } else {\n      return builder.build();\n    }\n  }\n\n  public static Executor newSingleThreadExecutor(String threadName) {\n    return Executors.newSingleThreadExecutor(new LeakCanarySingleThreadFactory(threadName));\n  }\n\n  public static void setLeakDirectoryProvider(LeakDirectoryProvider leakDirectoryProvider) {\n    if (LeakCanaryInternals.leakDirectoryProvider != null) {\n      throw new IllegalStateException(\"Cannot set the LeakDirectoryProvider after it has already \"\n          + \"been set. Try setting it before installing the RefWatcher.\");\n    }\n    LeakCanaryInternals.leakDirectoryProvider = leakDirectoryProvider;\n  }\n\n  public static LeakDirectoryProvider getLeakDirectoryProvider(Context context) {\n    LeakDirectoryProvider leakDirectoryProvider = LeakCanaryInternals.leakDirectoryProvider;\n    if (leakDirectoryProvider == null) {\n      leakDirectoryProvider = new DefaultLeakDirectoryProvider(context);\n    }\n    return leakDirectoryProvider;\n  }\n\n  private LeakCanaryInternals() {\n    throw new AssertionError();\n  }\n}\n","sourceCodeStart":180,"sourceCodeEnd":216,"githubUrl":"https://github.com/didi/DoKit/blob/626827cddb2feb2f3aee87a52a064b4e5ca2bed4/Android/dokit-leakcanary/src/main/java/com/squareup/leakcanary/internal/LeakCanaryInternals.java#L180-L216","documentation":"LeakCanaryInternals.setLeakDirectoryProvider() sets the process-wide directory provider used to store heap dumps. Because the analyzer, activities, and services all read this static field, it can only be set once; setting it after the RefWatcher is installed risks half the components using the old location, so a second set throws IllegalStateException.","triggerScenarios":"Calling LeakCanaryInternals.setLeakDirectoryProvider(provider) after a previous call, in particular after LeakCanary's buildAndInstall() already ran (installation itself configures the provider). Typical in debug tool setups (e.g. DoraemonKit panel) that let the user change the heap dump location at runtime.","commonSituations":"App initializes LeakCanary in Application.onCreate, then a debug menu tries to redirect heap dumps to a custom folder. Two libraries both attempting to configure the provider. Tests that reconfigure per test method without process reset.","solutions":["Call setLeakDirectoryProvider before buildAndInstall(), in the same single init block","Check the current state first: only set when LeakCanaryInternals-installed watcher is null / provider not yet set","If reconfiguration is genuinely needed, do it in a fresh process rather than at runtime"],"exampleFix":"// before\nLeakCanary.refWatcher(this).buildAndInstall();\nLeakCanaryInternals.setLeakDirectoryProvider(customProvider); // throws\n\n// after\nLeakCanaryInternals.setLeakDirectoryProvider(customProvider);\nLeakCanary.refWatcher(this).buildAndInstall();","handlingStrategy":"validation","validationCode":"// in the single init block, before install:\nLeakCanaryInternals.setLeakDirectoryProvider(customProvider);\nLeakCanary.refWatcher(context).buildAndInstall();","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Configure the directory provider and install the watcher in one startup block, in that order","Do not expose runtime reconfiguration of the heap dump directory in debug menus"],"tags":["leakcanary","android","initialization","configuration","java"],"backgroundTag":null,"analyzedSha":"626827cddb2feb2f3aee87a52a064b4e5ca2bed4","analyzedAt":"2026-08-14T12:45:58.758Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}