java-native-access/jna · error · IllegalArgumentException

Function <name> declared Structure[] at parameter <index> bu

Error message

Function <name> declared Structure[] at parameter <index> but array of <type> was passed

What it means

When a mapped function expects Structure.ByReference[] (an array of pointers to structures) but the caller passed an array whose component type is a by-value Structure subclass, JNA throws IllegalArgumentException because it cannot safely reinterpret by-value elements as by-reference.

Source

Thrown at src/com/sun/jna/Function.java:592

            return Boolean.TRUE.equals(arg) ? INTEGER_TRUE : INTEGER_FALSE;
        } else if (String[].class == argClass) {
            return new StringArray((String[])arg, encoding);
        } else if (WString[].class == argClass) {
            return new StringArray((WString[])arg);
        } else if (Pointer[].class == argClass) {
            return new PointerArray((Pointer[])arg);
        } else if (NativeMapped[].class.isAssignableFrom(argClass)) {
            return new NativeMappedArray((NativeMapped[])arg);
        } else if (Structure[].class.isAssignableFrom(argClass)) {
            // If the signature is Structure[], disallow
            // Structure.ByReference[] and Structure.ByReference elements
            Structure[] ss = (Structure[])arg;
            Class<?> type = argClass.getComponentType();
            boolean byRef = Structure.ByReference.class.isAssignableFrom(type);
            if (expectedType != null) {
                if (!Structure.ByReference[].class.isAssignableFrom(expectedType)) {
                    if (byRef) {
                        throw new IllegalArgumentException("Function " + getName()
                                                           + " declared Structure[] at parameter "
                                                           + index + " but array of "
                                                           + type + " was passed");
                    }
                    for (int i=0;i < ss.length;i++) {
                        if (ss[i] instanceof Structure.ByReference) {
                            throw new IllegalArgumentException("Function " + getName()
                                                               + " declared Structure[] at parameter "
                                                               + index + " but element " + i
                                                               + " is of Structure.ByReference type");
                        }
                    }
                }
            }
            if (byRef) {
                Structure.autoWrite(ss);
                Pointer[] pointers = new Pointer[ss.length + 1];
                for (int i=0;i < ss.length;i++) {

View on GitHub (pinned to d036ad9781)

Solutions

  1. Change the argument to a Structure.ByReference[] (construct elements as ByReference instances)
  2. Or change the mapping's expected parameter type to Structure[] if the native API takes the array by value
  3. Ensure consistent ByReference annotations across the interface and call sites

Example fix

// before
MyStruct[] arr = { new MyStruct() }; // by value
f(arr);
// after
MyStruct.ByReference[] arr = { new MyStruct.ByReference() };
f(arr);
Defensive patterns

Strategy: type-guard

Validate before calling

if (expectedType != null && Structure.ByReference[].class.isAssignableFrom(expectedType)) {
    for (Structure s : ss) {
        if (!(s instanceof Structure.ByReference)) throw new IllegalStateException("need ByReference elements");
    }
}

Type guard

boolean isByRefArray(Structure[] ss) {
    return ss.length == 0 || ss[0] instanceof Structure.ByReference;
}

Prevention

When it happens

Trigger: Calling a native function whose Java mapping declares Structure.ByReference[] (or an expectedType that is ByReference[]) while passing Structure[] where elements are by-value structures (not ByReference).

Common situations: Refactoring a struct array parameter from by-value to by-reference without updating call sites; mixing Structure and Structure.ByReference subclasses in the same codebase.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


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