{"record":{"id":"9a5f9e6d3e36e59d","repo":"skylot/jadx","slug":"input-class-can-t-be-saved-by-current-jadx-setting","errorCode":null,"errorMessage":"Input class can't be saved by current jadx settings (marked as DONT_GENERATE)","messagePattern":"Input class can't be saved by current jadx settings \\(marked as DONT_GENERATE\\)","errorType":"validation","errorClass":"JadxArgsValidateException","httpStatus":null,"severity":"error","filePath":"jadx-cli/src/main/java/jadx/cli/SingleClassMode.java","lineNumber":40,"sourceCode":"\tpublic static boolean process(JadxDecompiler jadx, JadxCLIArgs cliArgs) {\n\t\tString singleClass = cliArgs.getSingleClass();\n\t\tString singleClassOutput = cliArgs.getSingleClassOutput();\n\t\tif (singleClass == null && singleClassOutput == null) {\n\t\t\treturn false;\n\t\t}\n\t\tClassNode clsForProcess;\n\t\tif (singleClass != null) {\n\t\t\tclsForProcess = jadx.getRoot().resolveClass(singleClass);\n\t\t\tif (clsForProcess == null) {\n\t\t\t\tclsForProcess = jadx.getRoot().getClasses().stream()\n\t\t\t\t\t\t.filter(cls -> cls.getClassInfo().getAliasFullName().equals(singleClass))\n\t\t\t\t\t\t.findFirst().orElse(null);\n\t\t\t}\n\t\t\tif (clsForProcess == null) {\n\t\t\t\tthrow new JadxArgsValidateException(\"Input class not found: \" + singleClass);\n\t\t\t}\n\t\t\tif (clsForProcess.contains(AFlag.DONT_GENERATE)) {\n\t\t\t\tthrow new JadxArgsValidateException(\"Input class can't be saved by current jadx settings (marked as DONT_GENERATE)\");\n\t\t\t}\n\t\t\tif (clsForProcess.isInner()) {\n\t\t\t\tclsForProcess = clsForProcess.getTopParentClass();\n\t\t\t\tLOG.warn(\"Input class is inner, parent class will be saved: {}\", clsForProcess.getFullName());\n\t\t\t}\n\t\t} else {\n\t\t\t// singleClassOutput is set\n\t\t\t// expect only one class to be loaded\n\t\t\tList<ClassNode> classes = jadx.getRoot().getClasses().stream()\n\t\t\t\t\t.filter(c -> !c.isInner() && !c.contains(AFlag.DONT_GENERATE))\n\t\t\t\t\t.collect(Collectors.toList());\n\t\t\tint size = classes.size();\n\t\t\tif (size == 1) {\n\t\t\t\tclsForProcess = classes.get(0);\n\t\t\t} else {\n\t\t\t\tthrow new JadxArgsValidateException(\"Found \" + size + \" classes, single class output can't be used\");\n\t\t\t}\n\t\t}","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/skylot/jadx/blob/e738a26571d02919f01df40de93bc9a44dee4e18/jadx-cli/src/main/java/jadx/cli/SingleClassMode.java#L22-L58","documentation":"Thrown by RuntimeType.fromJdwpTag(int tag) when a JDWP value tag from the device does not match any of the sixteen standard JDWP.Tag constants handled by the switch (ARRAY, BYTE, CHAR, OBJECT, FLOAT, DOUBLE, INT, LONG, SHORT, VOID, BOOLEAN, STRING, THREAD, THREAD_GROUP, CLASS_LOADER, CLASS_OBJECT). All well-formed JDWP tags are covered, so reaching the default means the device sent a non-standard tag value or the byte stream is misaligned/corrupt. It is a protocol-level surprise from the debugged runtime.","triggerScenarios":"Decoding a JDWP value whose type tag byte is outside the spec's defined set, e.g. a vendor-specific tag from a non-conformant ART build, or a tag read from a misaligned packet buffer so the decoder reads the wrong byte as a tag. Fires while interpreting variable values returned to the debugger.","commonSituations":"Debugging on an unusual device/ROM whose ART emits tag values not in the standard set; a JDWP packet decode that got out of sync (wrong ID sizes from initJDWP); emulator with a non-standard runtime; reading a value whose encoding the current jdwp library does not model.","solutions":["Try debugging on a stock Android device/emulator image whose JDWP tags conform to the spec.","Upgrade jadx and its bundled jdwp library; newer versions may handle additional tags.","Verify the ID sizes negotiated in initJDWP are correct for the target (a wrong field size desynchronizes every subsequent tag read).","If you control the code, make fromJdwpTag return null and have callers skip the value rather than abort the debug session."],"exampleFix":"// before\ndefault:\n    throw new SmaliDebuggerException(\"Unexpected value: \" + tag);\n\n// after\ndefault:\n    LOG.warn(\"Unknown JDWP value tag: {}\", tag);\n    return null; // caller skips this value instead of killing the session","handlingStrategy":"validation","validationCode":"// Validate the tag is one JDWP actually defines before calling fromJdwpTag:\nif (!JDWP_TAG_SET.contains(tag)) {\n    LOG.warn(\"Skipping value with non-standard JDWP tag {}\", tag);\n    return null;\n}\nRuntimeType rt = RuntimeType.fromJdwpTag(tag);","typeGuard":"static boolean isKnownJdwpTag(int tag) {\n    return switch (tag) {\n        case JDWP.Tag.ARRAY, JDWP.Tag.BYTE, JDWP.Tag.CHAR, JDWP.Tag.OBJECT,\n             JDWP.Tag.FLOAT, JDWP.Tag.DOUBLE, JDWP.Tag.INT, JDWP.Tag.LONG,\n             JDWP.Tag.SHORT, JDWP.Tag.VOID, JDWP.Tag.BOOLEAN, JDWP.Tag.STRING,\n             JDWP.Tag.THREAD, JDWP.Tag.THREAD_GROUP, JDWP.Tag.CLASS_LOADER,\n             JDWP.Tag.CLASS_OBJECT -> true;\n        default -> false;\n    };\n}","tryCatchPattern":"RuntimeType rt;\ntry {\n    rt = RuntimeType.fromJdwpTag(tag);\n} catch (SmaliDebuggerException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"Unexpected value\")) {\n        LOG.warn(\"Non-standard JDWP tag {}, skipping value\", tag);\n        return null;\n    }\n    throw e;\n}","preventionTips":["Debug on stock Android images that emit spec-compliant JDWP tags.","Keep jadx and its jdwp library current for broader tag coverage.","Verify ID sizes negotiated in initJDWP so packet decoding stays aligned.","Make fromJdwpTag return null for unknown tags rather than aborting the session."],"tags":["debugger","jdwp","type-conversion","runtime"],"backgroundTag":null,"analyzedSha":"e738a26571d02919f01df40de93bc9a44dee4e18","analyzedAt":"2026-08-14T00:10:24.238Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}