{"record":{"id":"d358c81292054290","repo":"skylot/jadx","slug":"failed-to-save-json-file-d358c8","errorCode":null,"errorMessage":"Failed to save JSON file: {}","messagePattern":"Failed to save JSON file: (.+?)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"jadx-commons/jadx-analysis/src/main/java/jadx/analysis/callgraph/CallGraphExportJson.java","lineNumber":46,"sourceCode":"\tprivate final Gson gson;\n\n\tpublic CallGraphExportJson(ICallGraph callGraph) {\n\t\tthis.callGraph = callGraph;\n\t\tthis.gson = new GsonBuilder()\n\t\t\t\t.disableJdkUnsafe()\n\t\t\t\t.disableInnerClassSerialization()\n\t\t\t\t.setStrictness(Strictness.STRICT)\n\t\t\t\t// .setPrettyPrinting() // TODO: add option for pretty print?\n\t\t\t\t.create();\n\t}\n\n\tpublic void writeTo(Path path) {\n\t\ttry {\n\t\t\tFileUtils.makeDirsForFile(path);\n\t\t\tFiles.writeString(path, writeToString(), StandardCharsets.UTF_8,\n\t\t\t\t\tWRITE, TRUNCATE_EXISTING, CREATE);\n\t\t} catch (IOException e) {\n\t\t\tthrow new RuntimeException(\"Failed to save JSON file: \" + path, e);\n\t\t}\n\t}\n\n\tpublic String writeToString() {\n\t\tList<Edge> edges = new ArrayList<>();\n\t\tMap<Integer, Node> nodeMap = new HashMap<>();\n\t\tfor (ICallGraphEdge edge : callGraph.edges()) {\n\t\t\tICallGraphNode from = edge.from();\n\t\t\tICallGraphNode to = edge.to();\n\t\t\taddNode(from, nodeMap);\n\t\t\taddNode(to, nodeMap);\n\t\t\tEdge jsonEdge = new Edge();\n\t\t\tjsonEdge.from = from.getId();\n\t\t\tjsonEdge.to = to.getId();\n\t\t\tjsonEdge.resolved = edge.isResolved();\n\t\t\tedges.add(jsonEdge);\n\t\t}\n\t\tList<Node> nodes = new ArrayList<>(nodeMap.values());","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/skylot/jadx/blob/e738a26571d02919f01df40de93bc9a44dee4e18/jadx-commons/jadx-analysis/src/main/java/jadx/analysis/callgraph/CallGraphExportJson.java#L28-L64","documentation":"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.","triggerScenarios":"Calling CallGraphExportJson.writeTo(path) where the file cannot be created or written: permission denied, parent dir not creatable, disk full, invalid path.","commonSituations":"Output directory not writable; disk full; running in a sandboxed/containerized environment without a writable mount; relative path resolving to a read-only location.","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."],"exampleFix":"// before\nexporter.writeTo(Path.of(\"/sys/cg.json\"));\n// after\nFiles.createDirectories(Path.of(\"/tmp/cg\"));\nexporter.writeTo(Path.of(\"/tmp/cg/out.json\"));","handlingStrategy":"validation","validationCode":"Path parent = path.getParent();\nif (parent == null || !Files.isWritable(parent)) {\n    if (parent != null) Files.createDirectories(parent);\n}\nif (!Files.isWritable(path.getParent())) {\n    throw new IllegalStateException(\"Cannot write to: \" + path);\n}","typeGuard":"public static boolean isOutputWritable(Path p) {\n    Path parent = p.getParent();\n    return parent != null && Files.isWritable(parent);\n}","tryCatchPattern":"try {\n    export.writeTo(path);\n} catch (RuntimeException e) {\n    if (e.getMessage().startsWith(\"Failed to save JSON file\")) {\n        LOG.error(\"Call-graph JSON export failed for {}\", path, e.getCause());\n    } else throw e;\n}","preventionTips":["Pre-create the output directory.","Verify write permissions and free space before large exports.","Use absolute output paths."],"tags":["call-graph","io","export","json","jadx"],"backgroundTag":null,"analyzedSha":"e738a26571d02919f01df40de93bc9a44dee4e18","analyzedAt":"2026-08-14T00:10:24.238Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}