java-native-access/jna · error · IllegalArgumentException
setValue must not be called with type set to NULL
Error message
setValue must not be called with type set to NULL
What it means
EVT_VARIANT.setValue() in JNA's Winevt helper wraps an EVT_VARIANT union for the Windows Event Log API. It throws IllegalArgumentException when the caller passes a null EVT_VARIANT_TYPE, because without a type there is no way to know which union field to populate. The null check runs before any switch on the type, so this always fails fast.
Solutions
- Pass a non-null EVT_VARIANT_TYPE, e.g. EVT_VARIANT_TYPE.EvtVarTypeNull if you intend to clear the variant
- If the type comes from a variable or lookup, check for null before calling setValue and substitute EvtVarTypeNull
- If clearing the value, call setValue(EVT_VARIANT_TYPE.EvtVarTypeNull, null) instead of passing a null type
Example fix
// before variant.setValue(null, myValue); // after variant.setValue(EVT_VARIANT_TYPE.EvtVarTypeString, myValue); // or to clear: variant.setValue(EVT_VARIANT_TYPE.EvtVarTypeNull, null);
Defensive patterns
Strategy: validation
Validate before calling
if (type == null) {
type = EVT_VARIANT_TYPE.EvtVarTypeNull; // or throw a domain-specific error early
}
variant.setValue(type, value); Type guard
boolean isValidType(EVT_VARIANT_TYPE t) { return t != null; } Try / catch
try {
variant.setValue(type, value);
} catch (IllegalArgumentException e) {
log.warn("Bad EVT_VARIANT type/value: " + e.getMessage());
} Prevention
- Never pass a possibly-null enum obtained from a lookup map into setValue
- Default unknown types to EvtVarTypeNull rather than null
- Unit-test channel-config rendering with all EVT_VARIANT_TYPE values
When it happens
Trigger: Calling setValue(null, someValue) — e.g. passing an uninitialized or lookup-failed EVT_VARIANT_TYPE variable, or a method returning null type to renderChannelConfig/event-rendering code like testModifyChannelConfig.
Common situations: Mapping an EvtVariant field whose type was read from a struct and turned out null; passing the result of a map lookup (get(typeKey)) that missed; refactoring where the type variable was accidentally not initialized.
Related errors
- Function name may not be null
- Function name must not be null
- must be set from BOOL/BOOL[]
- must be set from byte[]
- must be set from byte/byte[]
AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12).
Data as JSON: /api/errors/6d09fce6b555b7f8.
Report an issue: GitHub.
Appendix: source
Thrown at contrib/platform/src/com/sun/jna/platform/win32/Winevt.java:274
public boolean isArray() {
return (Type & EVT_VARIANT_TYPE_ARRAY) == EVT_VARIANT_TYPE_ARRAY;
}
public EVT_VARIANT_TYPE getVariantType() {
return EVT_VARIANT_TYPE.values()[getBaseType()];
}
// Helper to store java object for set values
private Object holder;
/**
* @param type
* @param value
*/
public void setValue(EVT_VARIANT_TYPE type, Object value) {
allocateMemory();
if (type == null) {
throw new IllegalArgumentException("setValue must not be called with type set to NULL");
}
holder = null;
if (value == null || type == EVT_VARIANT_TYPE.EvtVarTypeNull) {
Type = EVT_VARIANT_TYPE.EvtVarTypeNull.ordinal();
Count = 0;
field1.writeField("pointerValue", Pointer.NULL);
} else {
switch (type) {
case EvtVarTypeAnsiString:
if (value.getClass().isArray() && value.getClass().getComponentType() == String.class) {
Type = type.ordinal() | EVT_VARIANT_TYPE_ARRAY;
StringArray sa = new StringArray((String[]) value, false);
holder = sa;
Count = ((String[]) value).length;
field1.writeField("pointerValue", sa);
} else if (value.getClass() == String.class) {
Type = type.ordinal();
Memory mem = new Memory(((String) value).length() + 1);View on GitHub (pinned to d036ad9781)