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

  1. Before setValue, verify new CFTypeRef(value).isTypeID(CoreFoundation.DICTIONARY_TYPE_ID).
  2. If a null assignment is intended, pass null explicitly (the check is skipped for null).
  3. Confirm the variable holding the pointer was produced by a Create/Copy CFDictionary call.
  4. 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

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


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)