java-native-access/jna · error · IllegalArgumentException
Structure field \"" + structField.name + "\" was declared…
Error message
Structure field \"" + structField.name + "\" was declared as " + structField.type + (structField.type == fieldType ? "" : " (native type " + fieldType + ")") + ", which is not supported within a Structure"
What it means
When JNA validates or marshals a structure field, an inner IllegalArgumentException from the type conversion is rethrown with a message naming the field, its declared Java type, and the attempted native type, explaining that the combination is not supported within a Structure. JNA only supports a fixed set of Java types in structure layouts.
Solutions
- Change the field type to a JNA-supported type (primitives, Pointer, String, WString, Buffer, arrays of primitives, nested Structure, Callback, NativeLong, etc.)
- Implement NativeMapped on the custom class, or register a TypeMapper via TypeMapper/mapper argument so the type can be converted
- Check the wrapped cause (the original IllegalArgumentException) for the exact conversion failure
- If using generics/boxed types, replace with the corresponding primitive or JNA numeric wrapper class intended for native sizes
Example fix
// before
class Cfg extends Structure {
public MyStatus status; // unsupported POJO
}
// after
class Cfg extends Structure {
public int status; // or implement NativeMapped on MyStatus
} Defensive patterns
Strategy: validation
Validate before calling
static boolean isJnaFieldType(java.lang.Class<?> t) {
return t.isPrimitive() || com.sun.jna.Pointer.class.isAssignableFrom(t)
|| t == String.class || t == com.sun.jna.WString.class
|| com.sun.jna.Structure.class.isAssignableFrom(t)
|| com.sun.jna.Callback.class.isAssignableFrom(t)
|| com.sun.jna.NativeMapped.class.isAssignableFrom(t)
|| (t.isArray() && isJnaFieldType(t.getComponentType()));
} Type guard
if (!isJnaFieldType(field.getType()) && mapper == null) {
throw new IllegalArgumentException("Unsupported structure field type: " + field.getType());
} Try / catch
try { struct.write(); } catch (IllegalArgumentException e) { /* unsupported field type: inspect e.getMessage() for field name */ } Prevention
- Only use documented JNA-supported field types
- Implement NativeMapped or a TypeMapper for custom classes
- Use primitives, not boxed types, for numeric fields
- Unit-test every Structure by calling write()/read() early
When it happens
Trigger: Declaring a Structure field of an unmapped type (e.g. boolean is supported, but arbitrary POJOs, boxed types not in the supported set, String without proper marshaling hints, arrays of unsupported element types, or a nested object that is neither Structure nor NativeMapped); passing an incompatible native type via a TypeMapper/NativeMapped conversion that itself throws IllegalArgumentException.
Common situations: Custom classes used as fields without implementing NativeMapped or having a TypeMapper; using Integer/Long wrappers instead of primitives in old JNA versions; forgetting to register a TypeMapper on the structure or library; arrays sized incorrectly.
Related errors
- Array fields must be initialized
- Callback type must be an interface
- Can't determine size of nested structure
- Can't instantiate " + type
- Exception reading field '" + f.getName() + "' in " +…
AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12).
Data as JSON: /api/errors/272f44331c4ea795.
Report an issue: GitHub.
Appendix: source
Thrown at src/com/sun/jna/Structure.java:913
// value is changed, keep the new native string alive
current.peer = nativeString;
value = nativeString.getPointer();
}
else {
nativeStrings.remove(structField.name);
}
}
try {
memory.setValue(offset, value, fieldType);
}
catch(IllegalArgumentException e) {
String msg = "Structure field \"" + structField.name
+ "\" was declared as " + structField.type
+ (structField.type == fieldType
? "" : " (native type " + fieldType + ")")
+ ", which is not supported within a Structure";
throw new IllegalArgumentException(msg, e);
}
}
/** Used to declare fields order as metadata instead of method.
* example:
* <pre><code>
* // New
* {@literal @}FieldOrder({ "n", "s" })
* class Parent extends Structure {
* public int n;
* public String s;
* }
* {@literal @}FieldOrder({ "d", "c" })
* class Son extends Parent {
* public double d;
* public char c;
* }
* // OldView on GitHub (pinned to d036ad9781)