java-native-access/jna · error · ClassCastException
Unable to cast to CFDictionary. Type ID
Error message
Unable to cast to CFDictionary. Type ID: {typeId} What it means
CFDictionaryRef.ByReference.setValue validates that the Pointer being assigned is a CFDictionary by comparing CFGetTypeID with DICTIONARY_TYPE_ID, throwing ClassCastException if it is not (null values are allowed and skip the check). This prevents storing a non-dictionary CFType into a dictionary-typed ByReference slot.
Solutions
- Before setValue, verify new CFTypeRef(value).isTypeID(CoreFoundation.DICTIONARY_TYPE_ID).
- If a null assignment is intended, pass null explicitly (the check is skipped for null).
- Confirm the variable holding the pointer was produced by a Create/Copy CFDictionary call.
- Log the offending type id to identify what object was actually passed.
Example fix
// before
byRef.setValue(somePointer); // throws if somePointer is a CFString
// after
CFTypeRef ref = new CFTypeRef(somePointer);
if (ref.isTypeID(CoreFoundation.DICTIONARY_TYPE_ID)) {
byRef.setValue(somePointer);
} else {
byRef.setValue(null); // or handle the mismatch
} Defensive patterns
Strategy: type-guard
Validate before calling
if (value == null || new CFTypeRef(value).isTypeID(CoreFoundation.DICTIONARY_TYPE_ID)) {
byRef.setValue(value);
} Type guard
boolean isCFDictionary(Pointer p) {
return p != null && new CFTypeRef(p).isTypeID(CoreFoundation.DICTIONARY_TYPE_ID);
} Try / catch
try {
byRef.setValue(value);
} catch (ClassCastException e) {
// assigned non-dictionary; inspect type id in message
} Prevention
- Only pass pointers produced by CFDictionary Create/Copy APIs to setValue
- Pass null explicitly to clear the slot (check is skipped for null)
- Validate with DICTIONARY_TYPE_ID before assignment
- Keep CFTypeRef producers and typed consumers clearly separated in code
When it happens
Trigger: Calling setValue(pointer) on a CFDictionaryRef.ByReference with a pointer to a CFString, CFArray, CFNumber, CFData, or any non-dictionary CFType obtained from generic CF calls.
Common situations: Populating out-parameters or struct fields from heterogeneous native results; wiring up the wrong variable to setValue; passing a result of a failed lookup that returned a different CFType.
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 CFNumber. Type ID
AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12).
Data as JSON: /api/errors/c3cf313f4654224f.
Report an issue: GitHub.
Appendix: source
Thrown at contrib/platform/src/com/sun/jna/platform/mac/CoreFoundation.java:398
/**
* Placeholder for a reference to a {@code CFDictionary} object.
*/
public static class ByReference extends PointerByReference {
public ByReference() {
this(null);
}
public ByReference(CoreFoundation.CFDictionaryRef value) {
super(value != null ? value.getPointer() : null);
}
@Override
public void setValue(Pointer value) {
if (value != null) {
CFTypeID typeId = INSTANCE.CFGetTypeID(value);
if (!DICTIONARY_TYPE_ID.equals(typeId)) {
throw new ClassCastException("Unable to cast to CFDictionary. Type ID: " + typeId);
}
}
super.setValue(value);
}
public CoreFoundation.CFDictionaryRef getDictionaryRefValue() {
Pointer value = super.getValue();
if (value == null) {
return null;
}
return new CoreFoundation.CFDictionaryRef(value);
}
}
public CFDictionaryRef() {
super();View on GitHub (pinned to d036ad9781)