skylot/jadx · error · JadxRuntimeException
No loaded files
Error message
No loaded files
What it means
Thrown by JadxDecompiler.getSaveTasks() when the internal root RootNode is null, meaning load() was never successfully called (or failed) before save() was invoked. Save requires the loaded class/resource tree, so without it there is nothing to write. It is a JadxRuntimeException (unchecked) with the literal message 'No loaded files'.
Source
Thrown at jadx-core/src/main/java/jadx/api/JadxDecompiler.java:308
public ITaskExecutor getSaveTaskExecutor() {
return getSaveTasks(!args.isSkipSources(), !args.isSkipResources());
}
@Deprecated(forRemoval = true)
public ExecutorService getSaveExecutor() {
ITaskExecutor executor = getSaveTaskExecutor();
executor.execute();
return executor.getInternalExecutor();
}
@Deprecated(forRemoval = true)
public List<Runnable> getSaveTasks() {
return Collections.singletonList(this::save);
}
private TaskExecutor getSaveTasks(boolean saveSources, boolean saveResources) {
if (root == null) {
throw new JadxRuntimeException("No loaded files");
}
OutDirs outDirs;
ExportGradle gradleExport;
if (args.getExportGradleType() != null) {
gradleExport = new ExportGradle(root, args.getOutDir(), getResources());
outDirs = gradleExport.init();
} else {
gradleExport = null;
outDirs = new OutDirs(args.getOutDirSrc(), args.getOutDirRes());
outDirs.makeDirs();
}
TaskExecutor executor = new TaskExecutor();
executor.setThreadsCount(args.getThreadsCount());
if (saveResources) {
// save resources first because decompilation can stop or fail
appendResourcesSaveTasks(executor, outDirs.getResOutDir());
}View on GitHub (pinned to e738a26571)
Solutions
- Always call decompiler.load() and ensure it completes without exception before calling save().
- Check decompiler.getRoot() == null (or getClasses().isEmpty()) before saving to guard the call.
- If load() failed, diagnose and fix that first; saving is impossible without loaded files.
- Structure your wrapper so load and save cannot be called out of order.
Example fix
// before
JadxDecompiler d = new JadxDecompiler(args);
d.save(); // root is null
// after
JadxDecompiler d = new JadxDecompiler(args);
d.load();
if (d.getClasses().isEmpty()) {
throw new IllegalStateException("load() produced no classes, nothing to save");
}
d.save(); Defensive patterns
Strategy: validation
Validate before calling
// Ensure load() ran successfully before saving.
if (decompiler.getClasses() == null || decompiler.getClasses().isEmpty()) {
throw new IllegalStateException("No classes loaded; call load() first.");
}
decompiler.save(); Try / catch
try {
decompiler.save();
} catch (JadxRuntimeException e) {
if ("No loaded files".equals(e.getMessage())) {
LOG.error("load() was not called or failed; cannot save.");
} else throw e;
} Prevention
- Always call and await load() before save().
- Do not swallow exceptions from load(); if it fails, do not proceed to save().
- Guard save() with a non-empty classes check.
When it happens
Trigger: Calling decompiler.save() or decompiler.getSaveTasks() without first calling (and completing) decompiler.load(), or calling save after a load() that threw and left root unpopulated.
Common situations: Programmatic integration that skips load(); a load() failure that was swallowed/ignored before save(); reordered initialization in a custom wrapper; unit tests that build a JadxDecompiler and jump straight to save.
Related errors
- Please specify input file
- Zip file is too big
- Failed to decompress zip entry: {}, error: {}
- File not found ${file.getAbsolutePath()}
- ${desc} directory exists as file ${dir}
AI-assisted analysis of skylot/jadx@e738a26571 (2026-08-14).
Data as JSON: /api/errors/6482c1dfb1275022.
Report an issue: GitHub.