java-native-access/jna · error · IllegalArgumentException
Invalid Structure field in " + getClass() + ", field name '"
Error message
Invalid Structure field in " + getClass() + ", field name '" + name + "' (" + type + "): " + e.getMessage() What it means
JNA validates every field of a Structure subclass by asking the layout engine for its native size. If a field's Java type has no native mapping (unknown class, un-sizeable type), IllegalArgumentException is thrown and re-wrapped with the Structure class, field name and type. It means the structure cannot be laid out in native memory.
Source
Thrown at src/com/sun/jna/Structure.java:1299
private void validateField(String name, Class<?> type) {
if (typeMapper != null) {
ToNativeConverter toNative = typeMapper.getToNativeConverter(type);
if (toNative != null) {
validateField(name, toNative.nativeType());
return;
}
}
if (type.isArray()) {
validateField(name, type.getComponentType());
}
else {
try {
getNativeSize(type);
}
catch(IllegalArgumentException e) {
String msg = "Invalid Structure field in " + getClass() + ", field name '" + name + "' (" + type + "): " + e.getMessage();
throw new IllegalArgumentException(msg, e);
}
}
}
/** ensure all fields are of valid type. */
private void validateFields() {
// Try to read the value under the read lock
cacheStructureLock.readLock().lock();
try {
if (validationMap.containsKey(getClass())) {
return; // Return because this Structure has already been validated
}
} finally {
cacheStructureLock.readLock().unlock();
}
// If not found, perform validation and update the cache under the write lock
cacheStructureLock.writeLock().lock();View on GitHub (pinned to d036ad9781)
Solutions
- Change the field to a JNA-supported type (primitive, wrapper, Pointer, String, WString, Buffer, arrays, nested Structure/Structure.ByReference, Callback)
- Register a TypeMapper (or use @Structure.FieldOrder-compatible custom marshalling) covering the custom field type
- If the type uses NativeMapped, verify the class implements nativeSize()/toNative()/fromNative() correctly
- Read the wrapped cause (e.getMessage) which states which type could not be sized
Example fix
// before
class Cfg extends Structure {
public MyCustomType cfg; // no native mapping
}
// after
class Cfg extends Structure {
public Pointer cfg; // or use a TypeMapper/NativeMapped for MyCustomType
} Defensive patterns
Strategy: type-guard
Validate before calling
for (Field f : Cfg.class.getFields()) {
Class<?> t = f.getType();
boolean ok = t.isPrimitive() || Number.class.isAssignableFrom(t) || t == Pointer.class
|| t == String.class || NativeMapped.class.isAssignableFrom(t)
|| Structure.class.isAssignableFrom(t) || t.isArray() || Callback.class.isAssignableFrom(t);
if (!ok) throw new IllegalStateException("Field not natively mappable: " + f);
} Type guard
static boolean isMappable(Class<?> t) {
return t.isPrimitive() || Number.class.isAssignableFrom(t) || t == Pointer.class
|| t == String.class || NativeMapped.class.isAssignableFrom(t)
|| (Structure.class.isAssignableFrom(t) && t != Structure.class)
|| (t.isArray() && t.getComponentType() != Structure.class)
|| (Callback.class.isAssignableFrom(t) && t.isInterface());
} Try / catch
try {
cfg.size();
} catch (IllegalArgumentException e) {
if (e.getCause() != null && e.getMessage().contains("Invalid Structure field")) {
throw new IllegalStateException("Fix unmapped structure field: " + e.getMessage(), e);
}
throw e;
} Prevention
- Only use documented JNA-native field types in Structures
- Implement NativeMapped or register a TypeMapper for custom types
- Write a unit test calling size() on every Structure to validate layout at build time
- Keep nested types concrete and supported
When it happens
Trigger: Defining a Structure field whose type has no registered native size: an unknown object type, a type not covered by the TypeMapper or a nested type that fails getNativeSize(type) during field validation (validateFields / calculateSize).
Common situations: Adding a custom class field to a Structure without a TypeMapper; typos in nested structure types; using types only valid after a type mapper is set; version changes where a previously supported type lost its mapping.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Unsupported type " + cls
- JNA: extract_value: %s
- Win32Exception(rc)
- Win32Exception(Kernel32.INSTANCE.GetLastError())
- Callback argument <nativeParamTypes[i]> requires custom type
AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12).
Data as JSON: /api/errors/f43f5813d23558cc.
Report an issue: GitHub.