clojure/clojure · error · IllegalArgumentException
Invalid descriptor
Error message
Invalid descriptor: ${descriptor} What it means
In getAbstractTypeFromDescriptor, if the very first character of the descriptor at the given offset is not one of the expected type-kind characters (primitive letter, '[', or 'L'), the descriptor is invalid for a verification type and IllegalArgumentException is thrown with the full remaining descriptor string. This is the outer (top-level) variant of the invalid-fragment check.
Solutions
- Fix the descriptor to a valid type descriptor (primitive letter, array '[...', or 'L...;').
- Ensure you pass a type descriptor, not a method descriptor or signature string.
- Correct offset computations so the substring starts at a real type character.
- Validate generated bytecode with CheckClassAdapter during development.
Example fix
// before frame.abstractType(0, "(I)V"); // method descriptor by mistake // after frame.abstractType(0, "I");
Defensive patterns
Strategy: validation
Validate before calling
static boolean isValidTypeDescriptor(String d) {
if (d == null || d.isEmpty()) return false;
char c = d.charAt(0);
if ("BCDFIJSZ".indexOf(c) >= 0) return d.length() == 1;
if (c == '[') return isValidTypeDescriptor(d.substring(1));
return c == 'L' && d.endsWith(";");
}
// call before passing into Frame/analyzer Try / catch
try {
frame.abstractType(offset, descriptor);
} catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("Invalid descriptor")) {
log.error("Expected a type descriptor, got: " + e.getMessage());
}
throw e;
} Prevention
- Pass type descriptors (I, Ljava/lang/String;), never method descriptors like (I)V.
- Build descriptors via Type.getDescriptor rather than string concatenation.
- Verify bytecode with CheckClassAdapter during development.
- Double-check buffer offsets when slicing descriptor strings.
When it happens
Trigger: Calling Frame abstractType/getAbstractTypeFromApiFormat with a descriptor starting with an illegal character, e.g. "x" or a method/signature string mistakenly passed where a type descriptor is expected.
Common situations: Passing a method descriptor like (I)V or a generic signature where a field/type descriptor is required; malformed locally generated bytecode being verified; off-by-one offsets into the descriptor buffer.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Invalid descriptor fragment
- Bytecode not available, can't check class version
- I/O error, can't check class version
- NestMember requires ASM7
- PermittedSubclasses requires ASM9
AI-assisted analysis of clojure/clojure@f3b143341d (2026-09-09).
Data as JSON: /api/errors/523a8099044c9922.
Report an issue: GitHub.
Appendix: source
Thrown at src/jvm/clojure/asm/Frame.java:383
typeValue = FLOAT;
break;
case 'J':
typeValue = LONG;
break;
case 'D':
typeValue = DOUBLE;
break;
case 'L':
internalName = buffer.substring(elementDescriptorOffset + 1, buffer.length() - 1);
typeValue = REFERENCE_KIND | symbolTable.addType(internalName);
break;
default:
throw new IllegalArgumentException(
"Invalid descriptor fragment: " + buffer.substring(elementDescriptorOffset));
}
return ((elementDescriptorOffset - offset) << DIM_SHIFT) | typeValue;
default:
throw new IllegalArgumentException("Invalid descriptor: " + buffer.substring(offset));
}
}
// -----------------------------------------------------------------------------------------------
// Methods related to the input frame
// -----------------------------------------------------------------------------------------------
/**
* Sets the input frame from the given method description. This method is used to initialize the
* first frame of a method, which is implicit (i.e. not stored explicitly in the StackMapTable
* attribute).
*
* @param symbolTable the type table to use to lookup and store type {@link Symbol}.
* @param access the method's access flags.
* @param descriptor the method descriptor.
* @param maxLocals the maximum number of local variables of the method.
*/
final void setInputFrameFromDescriptor(View on GitHub (pinned to f3b143341d)