{"record":{"id":"1feb49728a0ca0a2","repo":"skylot/jadx","slug":"unknown-file-format","errorCode":null,"errorMessage":"Unknown file format: ","messagePattern":"Unknown file format: ","errorType":"exception","errorClass":"JadxRuntimeException","httpStatus":null,"severity":"error","filePath":"jadx-core/src/main/java/jadx/core/clsp/ClsSet.java","lineNumber":196,"sourceCode":"\t}\n\n\tprivate static ClspClass getCls(String fullName, Map<String, ClspClass> names) {\n\t\tClspClass cls = names.get(fullName);\n\t\tif (cls == null) {\n\t\t\tLOG.debug(\"Class not found: {}\", fullName);\n\t\t}\n\t\treturn cls;\n\t}\n\n\tpublic void save(Path path) throws IOException {\n\t\tFileUtils.makeDirsForFile(path);\n\t\tString outputName = path.getFileName().toString();\n\t\tif (outputName.endsWith(CLST_EXTENSION)) {\n\t\t\ttry (BufferedOutputStream outputStream = new BufferedOutputStream(Files.newOutputStream(path))) {\n\t\t\t\tsave(outputStream);\n\t\t\t}\n\t\t} else {\n\t\t\tthrow new JadxRuntimeException(\"Unknown file format: \" + outputName);\n\t\t}\n\t}\n\n\tprivate void save(OutputStream output) throws IOException {\n\t\tDataOutputStream out = new DataOutputStream(output);\n\t\tout.writeBytes(JADX_CLS_SET_HEADER);\n\t\tout.writeByte(VERSION);\n\t\tout.writeInt(androidApiLevel);\n\n\t\tMap<String, ClspClass> names = new HashMap<>(classes.length);\n\t\tout.writeInt(classes.length);\n\t\tfor (ClspClass cls : classes) {\n\t\t\tout.writeInt(cls.getAccFlags());\n\t\t\twriteUnsignedByte(out, cls.getSource().ordinal());\n\t\t\tString clsName = cls.getName();\n\t\t\twriteString(out, clsName);\n\t\t\tnames.put(clsName, cls);\n\t\t}","sourceCodeStart":178,"sourceCodeEnd":214,"githubUrl":"https://github.com/skylot/jadx/blob/e738a26571d02919f01df40de93bc9a44dee4e18/jadx-core/src/main/java/jadx/core/clsp/ClsSet.java#L178-L214","documentation":"Thrown by ClsSet.save(Path) when the output file path does not end with the .jcst extension (CLST_EXTENSION). The save method only supports writing the jadx class set binary format to files with this specific extension; any other extension is rejected before serialization begins. This is a pure validation check on the output path.","triggerScenarios":"Calling ClsSet.save(path) where path.getFileName() does not end with '.jcst'. For example, passing a .json, .bin, or extensionless path. The check is case-sensitive and exact — '.JCST' or '.jcst.bak' would also fail.","commonSituations":"Programmatic callers that construct the output path dynamically and forget the extension. CLI or scripting workflows that pass an arbitrary output filename. Copy-paste errors where a different file extension is used.","solutions":["Ensure the output path ends with exactly '.jcst' (lowercase).","If building the path dynamically, append CLST_EXTENSION (or \".jcst\") to the filename.","Catch JadxRuntimeException around ClsSet.save and report the expected extension to the user."],"exampleFix":"// before\nclsSet.save(Path.of(\"/tmp/classpath-export\"));\n\n// after\nclsSet.save(Path.of(\"/tmp/classpath-export.jcst\"));","handlingStrategy":"validation","validationCode":"// Validate the output path ends with .jcst before calling save\nif (!outputPath.getFileName().toString().endsWith(\".jcst\")) {\n    throw new IllegalArgumentException(\n        \"Output path must end with .jcst, got: \" + outputPath.getFileName());\n}\nclsSet.save(outputPath);","typeGuard":"static boolean isValidJcstPath(Path path) {\n    String name = path.getFileName().toString();\n    return name.endsWith(\".jcst\");\n}","tryCatchPattern":null,"preventionTips":["Always construct output paths with the '.jcst' extension.","When building paths dynamically, append \".jcst\" to the base name.","Validate the path extension before calling save to provide a clearer error to the user."],"tags":["classpath","clst","save","validation","file-format"],"backgroundTag":null,"analyzedSha":"e738a26571d02919f01df40de93bc9a44dee4e18","analyzedAt":"2026-08-14T00:10:24.238Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}