java-native-access/jna · error · IllegalArgumentException

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

Error message

Function <name> declared Structure[] at parameter <index> but element <i> is of Structure.ByReference type

What it means

The inverse of error 326: if the mapping declares Structure[] by value, every element must NOT be a Structure.ByReference instance. A by-reference element in a by-value array is ambiguous for marshaling, so JNA rejects it at the specific offending index.

Source

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

        } 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++) {
                    pointers[i] = ss[i] != null ? ss[i].getPointer() : null;
                }
                return new PointerArray(pointers);
            } else if (ss.length == 0) {
                throw new IllegalArgumentException("Structure array must have non-zero length");
            } else if (ss[0] == null) {
                Structure.newInstance((Class<? extends Structure>) type).toArray(ss);

View on GitHub (pinned to d036ad9781)

Solutions

  1. Create all array elements as the by-value class (e.g. new MyStruct(), not new MyStruct.ByReference())
  2. If references are intended, change the mapping to Structure.ByReference[]
  3. Use Structure.newInstance(byValueClass).toArray(ss) to populate arrays with correct element types

Example fix

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

Strategy: type-guard

Validate before calling

for (int i = 0; i < ss.length; i++) {
    if (ss[i] instanceof Structure.ByReference)
        throw new IllegalStateException("by-value expected at element " + i);
}

Type guard

boolean isByValueArray(Structure[] ss) {
    for (Structure s : ss) if (s instanceof Structure.ByReference) return false;
    return true;
}

Prevention

When it happens

Trigger: Passing Structure[] where one or more elements were constructed as Structure.ByReference (directly or via newInstance of a ByReference subclass) while the function expects by-value structures.

Common situations: Mixing MyStruct and MyStruct.ByReference instances in one array after a refactor; auto-generated arrays that used ByReference for the element class.

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/bb04b9a7a1d501da. Report an issue: GitHub.