java-native-access/jna · error · IllegalArgumentException

must be set from String/String[]

Error message

 must be set from String/String[]

What it means

For EvtVarTypeAnsiString (and similar single-byte string types), setValue requires the value to be a String (or a String[] for the array form). Any other object type is rejected with this IllegalArgumentException, prefixed with the variant type name (e.g. 'EvtVarTypeAnsiString must be set from String/String[]'). The message's leading space comes from concatenating type.name() with the literal.

Source

Thrown at contrib/platform/src/com/sun/jna/platform/win32/Winevt.java:298

                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);
                            mem.setString(0, (String) value);
                            holder = mem;
                            Count = 0;
                            field1.writeField("pointerValue", mem);
                        } else {
                            throw new IllegalArgumentException(type.name() + " must be set from String/String[]");
                        }
                        break;
                    case EvtVarTypeBoolean:
                        if (value.getClass().isArray() && value.getClass().getComponentType() == BOOL.class) {
                            Type = type.ordinal() | EVT_VARIANT_TYPE_ARRAY;
                            Memory mem = new Memory(((BOOL[]) value).length * 4);
                            for (int i = 0; i < ((BOOL[]) value).length; i++) {
                                mem.setInt(i * 4, ((BOOL[]) value)[i].intValue());
                            }
                            holder = mem;
                            Count = 0;
                            field1.writeField("pointerValue", mem);
                        } else if (value.getClass() == BOOL.class) {
                            Type = type.ordinal();
                            Count = 0;
                            field1.writeField("intValue", ((BOOL) value).intValue());
                        } else {
                            throw new IllegalArgumentException(type.name() + " must be set from BOOL/BOOL[]");

View on GitHub (pinned to d036ad9781)

Solutions

  1. Convert the value to String: for byte[] use new String(bytes, StandardCharsets.US_ASCII) or StandardCharsets.UTF_8
  2. Use EvtVarTypeString with a wide-string-compatible call if the data is actually wide (UTF-16)
  3. Check the actual runtime class of value (value.getClass()) before the call to confirm it is String or String[]

Example fix

// before
variant.setValue(EVT_VARIANT_TYPE.EvtVarTypeAnsiString, asciiBytes);
// after
variant.setValue(EVT_VARIANT_TYPE.EvtVarTypeAnsiString, new String(asciiBytes, StandardCharsets.US_ASCII));
Defensive patterns

Strategy: type-guard

Validate before calling

if (!(value instanceof String) && !(value instanceof String[])) {
    throw new IllegalArgumentException("AnsiString requires String or String[]");
}

Type guard

boolean isAnsiStringCompatible(Object v) {
    return v instanceof String || (v != null && v.getClass() == String[].class);
}

Try / catch

try {
    variant.setValue(EVT_VARIANT_TYPE.EvtVarTypeAnsiString, value);
} catch (IllegalArgumentException e) {
    value = String.valueOf(value); // fallback conversion, then retry
    variant.setValue(EVT_VARIANT_TYPE.EvtVarTypeAnsiString, value);
}

Prevention

When it happens

Trigger: setValue(EVT_VARIANT_TYPE.EvtVarTypeAnsiString, value) where value is not a String and not a String[] — e.g. a byte[], a WideChar-backed object, Integer, or a CharSequence.

Common situations: Passing a value read from another variant/union without converting to String; assuming ANSI and wide string types are interchangeable; passing a byte[] that actually holds ASCII text.

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


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