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

  1. Inspect getCause() on the JadxRuntimeException to find the scheduler's original error.
  2. If using a custom IDecompileScheduler, verify its buildBatches contract and that it never throws on cyclic deps.
  3. Try reducing the input (decompile a subset) to isolate the offending class/dependency.
  4. 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

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


AI-assisted analysis of skylot/jadx@e738a26571 (2026-08-14). Data as JSON: /api/errors/c0d94775f51ef623. Report an issue: GitHub.