skylot/jadx · error · RuntimeException
Failed to save JSON file: {}
Error message
Failed to save JSON file: {} What it means
Thrown by CallGraphExportJson.writeTo(Path) as a plain RuntimeException wrapping an IOException during the call-graph JSON export write. Same pattern as the DOT exporter: mkdirs-for-file then Files.writeString with WRITE/TRUNCATE_EXISTING/CREATE.
Source
Thrown at jadx-commons/jadx-analysis/src/main/java/jadx/analysis/callgraph/CallGraphExportJson.java:46
private final Gson gson;
public CallGraphExportJson(ICallGraph callGraph) {
this.callGraph = callGraph;
this.gson = new GsonBuilder()
.disableJdkUnsafe()
.disableInnerClassSerialization()
.setStrictness(Strictness.STRICT)
// .setPrettyPrinting() // TODO: add option for pretty print?
.create();
}
public void writeTo(Path path) {
try {
FileUtils.makeDirsForFile(path);
Files.writeString(path, writeToString(), StandardCharsets.UTF_8,
WRITE, TRUNCATE_EXISTING, CREATE);
} catch (IOException e) {
throw new RuntimeException("Failed to save JSON file: " + path, e);
}
}
public String writeToString() {
List<Edge> edges = new ArrayList<>();
Map<Integer, Node> nodeMap = new HashMap<>();
for (ICallGraphEdge edge : callGraph.edges()) {
ICallGraphNode from = edge.from();
ICallGraphNode to = edge.to();
addNode(from, nodeMap);
addNode(to, nodeMap);
Edge jsonEdge = new Edge();
jsonEdge.from = from.getId();
jsonEdge.to = to.getId();
jsonEdge.resolved = edge.isResolved();
edges.add(jsonEdge);
}
List<Node> nodes = new ArrayList<>(nodeMap.values());View on GitHub (pinned to e738a26571)
Solutions
- Ensure the target directory exists and is writable.
- Use an absolute, writable path.
- Free disk space and retry.
- Inspect the wrapped IOException for the OS error.
Example fix
// before
exporter.writeTo(Path.of("/sys/cg.json"));
// after
Files.createDirectories(Path.of("/tmp/cg"));
exporter.writeTo(Path.of("/tmp/cg/out.json")); Defensive patterns
Strategy: validation
Validate before calling
Path parent = path.getParent();
if (parent == null || !Files.isWritable(parent)) {
if (parent != null) Files.createDirectories(parent);
}
if (!Files.isWritable(path.getParent())) {
throw new IllegalStateException("Cannot write to: " + path);
} Type guard
public static boolean isOutputWritable(Path p) {
Path parent = p.getParent();
return parent != null && Files.isWritable(parent);
} Try / catch
try {
export.writeTo(path);
} catch (RuntimeException e) {
if (e.getMessage().startsWith("Failed to save JSON file")) {
LOG.error("Call-graph JSON export failed for {}", path, e.getCause());
} else throw e;
} Prevention
- Pre-create the output directory.
- Verify write permissions and free space before large exports.
- Use absolute output paths.
When it happens
Trigger: Calling CallGraphExportJson.writeTo(path) where the file cannot be created or written: permission denied, parent dir not creatable, disk full, invalid path.
Common situations: Output directory not writable; disk full; running in a sandboxed/containerized environment without a writable mount; relative path resolving to a read-only location.
Related errors
- Failed to save JSON file: {}
- Failed to init common directories
- Failed to create temp root directory
- {}
- Failed to open zip: {}
AI-assisted analysis of skylot/jadx@e738a26571 (2026-08-14).
Data as JSON: /api/errors/d358c81292054290.
Report an issue: GitHub.