didi/DoKit · error · IllegalArgumentException
maxStoredHeapDumps must be at least 1
Error message
maxStoredHeapDumps must be at least 1
What it means
DefaultLeakDirectoryProvider stores heap dumps in app storage and prunes old ones to stay under maxStoredHeapDumps. Its constructor validates that the cap is at least 1; zero or negative would mean heap dumps can never be persisted, so the constructor fails fast with IllegalArgumentException.
Source
Thrown at Android/dokit-leakcanary/src/main/java/com/squareup/leakcanary/DefaultLeakDirectoryProvider.java:67
private static final String HPROF_SUFFIX = ".hprof";
private static final String PENDING_HEAPDUMP_SUFFIX = "_pending" + HPROF_SUFFIX;
/** 10 minutes */
private static final int ANALYSIS_MAX_DURATION_MS = 10 * 60 * 1000;
private final Context context;
private final int maxStoredHeapDumps;
private volatile boolean writeExternalStorageGranted;
private volatile boolean permissionNotificationDisplayed;
public DefaultLeakDirectoryProvider(@NonNull Context context) {
this(context, DEFAULT_MAX_STORED_HEAP_DUMPS);
}
public DefaultLeakDirectoryProvider(@NonNull Context context, int maxStoredHeapDumps) {
if (maxStoredHeapDumps < 1) {
throw new IllegalArgumentException("maxStoredHeapDumps must be at least 1");
}
this.context = context.getApplicationContext();
this.maxStoredHeapDumps = maxStoredHeapDumps;
}
@Override
public @NonNull
List<File> listFiles(@NonNull FilenameFilter filter) {
if (!hasStoragePermission()) {
requestWritePermissionNotification();
}
List<File> files = new ArrayList<>();
File[] externalFiles = externalStorageDirectory().listFiles(filter);
if (externalFiles != null) {
files.addAll(Arrays.asList(externalFiles));
}
View on GitHub (pinned to 626827cddb)
Solutions
- Pass a value >= 1; LeakCanary's own default is DEFAULT_MAX_STORED_HEAP_DUMPS (7)
- If the intent was 'disable leak analysis', do not construct the provider — build a disabled RefWatcher (RefWatcher.DISABLED) instead
- Clamp user-supplied settings: Math.max(1, configuredValue) at the configuration boundary
Example fix
// before new DefaultLeakDirectoryProvider(context, 0); // after new DefaultLeakDirectoryProvider(context, Math.max(1, config.maxHeapDumps));
Defensive patterns
Strategy: validation
Validate before calling
int capped = Math.max(1, configuredMaxHeapDumps); new DefaultLeakDirectoryProvider(context, capped);
Prevention
- Clamp user/remote-config values to >= 1 at the configuration boundary
- Use RefWatcher.DISABLED to turn analysis off rather than a zero cap
When it happens
Trigger: Constructing new DefaultLeakDirectoryProvider(context, maxStoredHeapDumps) with 0 or a negative value — typically from a hardcoded config, a BuildConfig field, or a computed value (e.g. user preference mapped to 'keep no dumps') that was never validated.
Common situations: Teams wiring LeakCanary config from a remote-config or debug-settings screen where 0 is used to mean 'disable heap dumps'. Copy-pasted builder code with a placeholder 0. Using the DoraemonKit wrapper that exposes this provider with a configurable dump count.
Related errors
- Cannot set the LeakDirectoryProvider after it has already be
- leakTraceAsFakeException() can only be called when leakFound
- buildAndInstall() should only be called once.
- Could not find char array in {}
- File does not exist: {}
AI-assisted analysis of didi/DoKit@626827cddb (2026-08-14).
Data as JSON: /api/errors/54bb7619ab2678bd.
Report an issue: GitHub.