skylot/jadx · error · JadxRuntimeException
Decompilation batches build failed
Error message
Decompilation batches build failed
What it means
Thrown in appendSourcesSave() when decompileScheduler.buildBatches(processQueue) raises any exception while grouping the filtered class list into decompilation batches. Batching depends on resolving inter-class dependencies, so a failure here is structural (cyclic or unresolvable dependencies, a null class node, scheduler misconfiguration). The original exception is chained on a JadxRuntimeException.
Source
Thrown at jadx-core/src/main/java/jadx/api/JadxDecompiler.java:404
int endIdx = inputFileName.lastIndexOf(':');
if (endIdx != -1) {
int startIdx = inputFileName.lastIndexOf(':', endIdx - 1) + 1;
inputFileName = inputFileName.substring(startIdx, endIdx);
}
}
set.add(inputFileName);
}
return set;
}
private void appendSourcesSave(ITaskExecutor executor, File outDir) {
List<JavaClass> classes = getClasses();
List<JavaClass> processQueue = filterClasses(classes);
List<List<JavaClass>> batches;
try {
batches = decompileScheduler.buildBatches(processQueue);
} catch (Exception e) {
throw new JadxRuntimeException("Decompilation batches build failed", e);
}
List<Runnable> decompileTasks = new ArrayList<>(batches.size());
for (List<JavaClass> decompileBatch : batches) {
decompileTasks.add(() -> {
for (JavaClass cls : decompileBatch) {
try {
ClassNode clsNode = cls.getClassNode();
ICodeInfo code = clsNode.getCode();
SaveCode.save(outDir, clsNode, code);
} catch (Exception e) {
LOG.error("Error saving class: {}", cls, e);
}
}
});
}
executor.addParallelTasks(decompileTasks);
}View on GitHub (pinned to e738a26571)
Solutions
- Inspect getCause() on the JadxRuntimeException to find the scheduler's original error.
- If using a custom IDecompileScheduler, verify its buildBatches contract and that it never throws on cyclic deps.
- Try reducing the input (decompile a subset) to isolate the offending class/dependency.
- Report with the cause stack trace if it reproduces on stock jadx, as this usually indicates an internal bug.
Defensive patterns
Strategy: try-catch
Try / catch
try {
decompiler.save();
} catch (JadxRuntimeException e) {
if ("Decompilation batches build failed".equals(e.getMessage())) {
LOG.error("Scheduler failed to build batches", e.getCause());
// fall back to decompiling classes individually without batching
} else throw e;
} Prevention
- Inspect getCause() to find the scheduler's underlying error.
- If using a custom IDecompileScheduler, ensure buildBatches never throws on cyclic deps.
- Isolate the failing class by decompiling subsets when reproducing.
When it happens
Trigger: Calling save() (which internally calls appendSourcesSave) on a loaded project where the decompile scheduler cannot partition the class graph into batches. Reached only after load() succeeded.
Common situations: A class graph containing unusual cyclic dependencies that the scheduler's batcher cannot handle; a custom/buggy IDecompileScheduler implementation; a corrupted class node introduced by a plugin; very large codebases that expose an edge case in batching.
Related errors
- Fallback parser can't find entry: {}
- Missing class:
- Unknown file format:
- Cannot save type:
- Code not generated for class {}
AI-assisted analysis of skylot/jadx@e738a26571 (2026-08-14).
Data as JSON: /api/errors/c0d94775f51ef623.
Report an issue: GitHub.