java-native-access/jna · error · IllegalArgumentException

Structure array must have non-zero length

Error message

Structure array must have non-zero length

What it means

A zero-length Structure array cannot be marshaled because JNA derives the native pointer from the first element (ss[0].getPointer()); there is no element to take an address from. JNA therefore rejects empty arrays with IllegalArgumentException.

Source

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

                    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);
                return ss[0].getPointer();
            } else {
                Structure.autoWrite(ss);
                return ss[0].getPointer();
            }
        } else if (argClass.isArray()){
            throw new IllegalArgumentException("Unsupported array argument type: "
                                               + argClass.getComponentType());
        } else if (allowObjects) {
            return arg;
        } else if (!Native.isSupportedNativeType(arg.getClass())) {
            throw new IllegalArgumentException("Unsupported argument type "
                                               + arg.getClass().getName()
                                               + " at parameter " + index
                                               + " of function " + getName());
        }

View on GitHub (pinned to d036ad9781)

Solutions

  1. Guard the call site: if the array is empty, pass Pointer.NULL (or null) instead of an empty Structure[]
  2. Model the native API as (Pointer, int count) and pass null plus 0 for the empty case
  3. Allocate at least one element if the native API requires a real array (even a dummy)

Example fix

// before
f(new MyStruct[0]);
// after
f(items.isEmpty() ? null : items.toArray(new MyStruct[0]));
Defensive patterns

Strategy: validation

Validate before calling

if (ss.length == 0) {
    nativeCall(null, 0); // or pass Pointer.NULL per your API mapping
} else {
    nativeCall(ss, ss.length);
}

Try / catch

try {
    f.invoke(...);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("non-zero length")) { /* pass NULL/0 instead */ }
}

Prevention

When it happens

Trigger: Passing new MyStruct[0] (or a List.toArray into an empty array) as a Structure[] argument to a native function.

Common situations: Passing a Java-side empty collection result straight into a native call without a null-pointer / count protocol; native API expecting (NULL, 0) pattern that the Java mapping doesn't model.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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