java-native-access/jna · error · ClassCastException
Unable to cast to CFNumber. Type ID
Error message
Unable to cast to CFNumber. Type ID: {getTypeID()} What it means
CFNumberRef wraps a Core Foundation pointer and validates on construction that the native object's CFTypeID matches the CFNumber type. If the Pointer points at some other CFType (a string, array, dictionary, null type id 0), the constructor throws ClassCastException immediately rather than allowing an invalid downcast to be used later.
Solutions
- Before constructing, call INSTANCE.CFGetTypeID(pointer) (or wrap in CFTypeRef and use getTypeID()) and compare with CoreFoundation.NUMBER_TYPE_ID.
- Wrap polymorphic lookups in a CFTypeRef first and branch on getTypeID() before narrowing.
- Check for a NULL pointer (missing key) before casting.
- If you expected a number but got a different type, fix the key/type assumption in the code reading the native structure.
Example fix
// before
CFNumberRef num = new CFNumberRef(dictValue); // throws if value is a CFString
// after
CFTypeRef ref = new CFTypeRef(dictValue);
if (ref.isTypeID(CoreFoundation.NUMBER_TYPE_ID)) {
CFNumberRef num = new CFNumberRef(dictValue);
} else {
// handle non-number value
} Defensive patterns
Strategy: type-guard
Validate before calling
if (value != null && new CFTypeRef(value).isTypeID(CoreFoundation.NUMBER_TYPE_ID)) {
CFNumberRef num = new CFNumberRef(value);
} Type guard
boolean isCFNumber(Pointer p) {
return p != null && new CFTypeRef(p).isTypeID(CoreFoundation.NUMBER_TYPE_ID);
} Try / catch
try {
CFNumberRef num = new CFNumberRef(value);
long v = num.longValue();
} catch (ClassCastException e) {
// value is not a CFNumber; inspect new CFTypeRef(value).getTypeID()
} Prevention
- Always narrow via CFTypeRef.isTypeID before constructing typed refs
- Null-check dictionary lookups — missing keys return NULL (type id 0)
- Remember CF collections hold CFTypeRefs; check each element's type
- CFTypeIDs are process-specific; use the interface constants, never hardcoded ids
When it happens
Trigger: Constructing new CFNumberRef(pointer) with a pointer obtained from CFDictionaryGetValue, CFArrayGetValueAtIndex, or any polymorphic CFTypeRef API where the underlying object is not actually a CFNumber (or the pointer is NULL, whose type id is 0).
Common situations: Reading heterogeneous CFDictionary values and blindly casting every value to CFNumberRef when some values are strings or booleans; stale/released CF objects whose memory was reused; passing a NULL Pointer (e.g. missing dictionary key).
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Unable to cast to CFArray. Type ID
- Unable to cast to CFBoolean. Type ID
- Unable to cast to CFData. Type ID
- Unable to cast to CFDictionary. Type ID
- Unable to cast to CFDictionary. Type ID
AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12).
Data as JSON: /api/errors/a4e1fda655a40e60.
Report an issue: GitHub.
Appendix: source
Thrown at contrib/platform/src/com/sun/jna/platform/mac/CoreFoundation.java:148
* A reference type used in many Core Foundation parameters and function
* results. It refers to a {@code CFAllocator} object, which allocates,
* reallocates, and deallocates memory for Core Foundation objects.
*/
class CFAllocatorRef extends CFTypeRef {
}
/**
* A reference to a {@code CFNumber} object.
*/
class CFNumberRef extends CFTypeRef {
public CFNumberRef() {
super();
}
public CFNumberRef(Pointer p) {
super(p);
if (!isTypeID(NUMBER_TYPE_ID)) {
throw new ClassCastException("Unable to cast to CFNumber. Type ID: " + getTypeID());
}
}
/**
* Convert this {@code CFNumber} to a {@code long}.
* <p>
* This method assumes a 64-bit integer is stored and does not do type checking.
* Users should use {@link #CFNumberGetType} to determine the appropriate type
* conversion. If this object's type differs from the return type, and the
* conversion is lossy or the return value is out of range, then this method
* returns an approximate value.
*
* @return The corresponding {@code long}
*/
public long longValue() {
LongByReference lbr = new LongByReference();
INSTANCE.CFNumberGetValue(this, CFNumberType.kCFNumberLongLongType.typeIndex(), lbr);
return lbr.getValue();View on GitHub (pinned to d036ad9781)