java-native-access/jna · error · IllegalArgumentException

CFString conversion fails or the provided buffer is too…

Error message

CFString conversion fails or the provided buffer is too small.

What it means

CFStringRef.stringValue() converts a CoreFoundation string to a Java String via CFStringGetCString into a UTF-8 buffer sized from CFStringGetMaximumCStringSize plus 1. If the conversion fails (invalid CFString, embedded nulls, or the buffer was somehow too small), CFStringGetCString returns 0 and this IllegalArgumentException is thrown.

Solutions

  1. Verify the dictionary value is actually a CFString before casting (check CFGetTypeID against CFStringGetTypeID())
  2. Wrap stringValue() in try-catch for IllegalArgumentException and fall back to an empty/default string
  3. Check that the CFStringRef pointer is non-null (ref.equals(Pointer.NULL) is false) before calling stringValue()

Example fix

// before
String name = cfDictionaryRef.getStringProperty(key);
// after
String name;
try {
    name = cfDictionaryRef.getStringProperty(key);
} catch (IllegalArgumentException e) {
    name = ""; // value was not a convertible CFString
}
Defensive patterns

Strategy: try-catch

Validate before calling

// check pointer validity first
if (cfStringRef == null || cfStringRef.getPointer() == null || Pointer.NULL.equals(cfStringRef.getPointer())) {
    throw new IllegalArgumentException("CFStringRef has no valid pointer");
}

Type guard

boolean isConvertible(CFStringRef s) { return s != null && s.getPointer() != null; }

Try / catch

try { value = cfString.stringValue(); } catch (IllegalArgumentException e) { value = ""; }

Prevention

When it happens

Trigger: Calling stringValue() on a CFStringRef whose native pointer is invalid or whose content cannot be encoded to UTF-8 as a C string; callers include getStringProperty on CFDictionary values, window list descriptions, and locale date/time formats where a key holds a non-string value.

Common situations: Reading a CFDictionary property that does not actually contain a CFString (e.g. a CFNumber or CFBoolean cast as CFStringRef); corrupted or already-released CFString references from CoreGraphics/CoreFoundation APIs; macOS API changes returning unexpected types.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12). Data as JSON: /api/errors/deb9120824940c8d. Report an issue: GitHub.

Appendix: source

Thrown at contrib/platform/src/com/sun/jna/platform/mac/CoreFoundation.java:588

            // Get number of characters (UTF-16 code pairs)
            // Code points > 0xffff will have 2 characters per Unicode character
            CFIndex length = INSTANCE.CFStringGetLength(this);
            if (length.longValue() == 0) {
                return "";
            }
            // Calculate maximum possible size in UTF8 bytes
            // This will be 3 x length
            CFIndex maxSize = INSTANCE.CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8);
            if (maxSize.intValue() == kCFNotFound) {
                throw new StringIndexOutOfBoundsException("CFString maximum number of bytes exceeds LONG_MAX.");
            }
            // Increment size by 1 for a null byte
            maxSize.setValue(maxSize.longValue() + 1);
            Memory buf = new Memory(maxSize.longValue());
            if (0 != INSTANCE.CFStringGetCString(this, buf, maxSize, kCFStringEncodingUTF8)) {
                return buf.getString(0, "UTF8");
            }
            throw new IllegalArgumentException("CFString conversion fails or the provided buffer is too small.");
        }
    }

    /**
     * A wrapper for the {@link NativeLong} type, used for {@link CFNumberRef}
     * types, {@link CFStringRef} lengths, and {@link CFArrayRef} sizes and indices.
     */
    class CFIndex extends NativeLong {
        private static final long serialVersionUID = 1L;

        public CFIndex() {
            super();
        }

        public CFIndex(long value) {
            super(value);
        }
    }

View on GitHub (pinned to d036ad9781)