{"record":{"id":"b2a1593f68be72da","repo":"skylot/jadx","slug":"cannot-save-type","errorCode":null,"errorMessage":"Cannot save type: ","messagePattern":"Cannot save type: ","errorType":"exception","errorClass":"JadxRuntimeException","httpStatus":null,"severity":"error","filePath":"jadx-core/src/main/java/jadx/core/clsp/ClsSet.java","lineNumber":303,"sourceCode":"\t\t\tif (bound != ArgType.WildcardBound.UNBOUND) {\n\t\t\t\twriteArgType(out, argType.getWildcardType(), names);\n\t\t\t}\n\t\t} else if (argType.isGeneric()) {\n\t\t\tout.writeByte(TypeEnum.GENERIC.ordinal());\n\t\t\tout.writeInt(getCls(argType, names).getId());\n\t\t\twriteArgTypesList(out, argType.getGenericTypes(), names);\n\t\t} else if (argType.isGenericType()) {\n\t\t\tout.writeByte(TypeEnum.GENERIC_TYPE_VARIABLE.ordinal());\n\t\t\twriteString(out, argType.getObject());\n\t\t\twriteArgTypesList(out, argType.getExtendTypes(), names);\n\t\t} else if (argType.isObject()) {\n\t\t\tout.writeByte(TypeEnum.OBJECT.ordinal());\n\t\t\tout.writeInt(getCls(argType, names).getId());\n\t\t} else if (argType.isArray()) {\n\t\t\tout.writeByte(TypeEnum.ARRAY.ordinal());\n\t\t\twriteArgType(out, argType.getArrayElement(), names);\n\t\t} else {\n\t\t\tthrow new JadxRuntimeException(\"Cannot save type: \" + argType);\n\t\t}\n\t}\n\n\tprivate void load(InputStream input) throws IOException, DecodeException {\n\t\ttry (DataInputStream in = new DataInputStream(new BufferedInputStream(input))) {\n\t\t\tbyte[] header = new byte[JADX_CLS_SET_HEADER.length()];\n\t\t\tint readHeaderLength = in.read(header);\n\t\t\tif (readHeaderLength != JADX_CLS_SET_HEADER.length()\n\t\t\t\t\t|| !JADX_CLS_SET_HEADER.equals(new String(header, STRING_CHARSET))) {\n\t\t\t\tthrow new DecodeException(\"Wrong jadx class set header\");\n\t\t\t}\n\t\t\tint version = in.readByte();\n\t\t\tif (version != VERSION) {\n\t\t\t\tthrow new DecodeException(\"Wrong jadx class set version, got: \" + version + \", expect: \" + VERSION);\n\t\t\t}\n\t\t\tandroidApiLevel = in.readInt();\n\t\t\tint clsCount = in.readInt();\n\t\t\tclasses = new ClspClass[clsCount];","sourceCodeStart":285,"sourceCodeEnd":321,"githubUrl":"https://github.com/skylot/jadx/blob/e738a26571d02919f01df40de93bc9a44dee4e18/jadx-core/src/main/java/jadx/core/clsp/ClsSet.java#L285-L321","documentation":"Thrown by ClsSet.writeArgType during serialization when an ArgType does not match any of the recognized type categories (primitive, outer-generic, wildcard, generic, generic-type-variable, object, or array). The method cascades through if-else checks for each type kind and throws if none match. This indicates the ArgType is in an unexpected or corrupt state that the serializer cannot handle.","triggerScenarios":"Calling ClsSet.save (which calls writeArgType for every type in the class set) where an ArgType instance has an internal state that does not satisfy any of the isPrimitive/getOuterType/getWildcardType/isGeneric/isGenericType/isObject/isArray predicates. This could happen if a custom ArgType subclass or a malformed ArgType is present in the class graph.","commonSituations":"A jadx internal bug where a new ArgType variant is introduced without updating writeArgType. Processing obfuscated bytecode that produces an ArgType in an inconsistent state. Custom jadx extensions that create ArgType instances without populating the expected fields. Extremely rare in normal operation.","solutions":["Inspect the ArgType value in the error message to determine its state (call isPrimitive, isObject, etc. to see which predicates fail).","Report as a jadx internal bug — all valid ArgType states should be serializable; a gap means writeArgType needs a new branch.","If writing a custom jadx extension that produces ArgType instances, ensure they satisfy at least one category predicate (isPrimitive, isObject, isArray, isGeneric, isGenericType, getOuterType, or getWildcardType)."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"// Check that an ArgType falls into at least one serializable category\nstatic boolean isSerializableArgType(ArgType t) {\n    return t == null\n        || t.isPrimitive()\n        || t.getOuterType() != null\n        || t.getWildcardType() != null\n        || t.isGeneric()\n        || t.isGenericType()\n        || t.isObject()\n        || t.isArray();\n}","tryCatchPattern":"try {\n    clsSet.save(outputPath);\n} catch (JadxRuntimeException e) {\n    if (e.getMessage().startsWith(\"Cannot save type:\")) {\n        LOG.error(\"Unserializable ArgType encountered: {}\", e.getMessage());\n        // report which type caused the failure\n    } else {\n        throw e;\n    }\n}","preventionTips":["Report this as a jadx internal bug if encountered — all valid ArgType states should be serializable.","Check the ArgType value in the message to understand which predicate it fails.","Avoid custom ArgType subclasses or modifications that create unhandled type states."],"tags":["classpath","clst","serialization","argtype","internal"],"backgroundTag":null,"analyzedSha":"e738a26571d02919f01df40de93bc9a44dee4e18","analyzedAt":"2026-08-14T00:10:24.238Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}