oracle/graal · error · IllegalArgumentException

Unsupported type %s

Error message

Unsupported type %s

What it means

BinaryOutput.writeValue supports only a fixed set of boxed types — Boolean, Byte/Short/Integer-like integral boxes ending at LONG, Float, Double, and String (plus null/array handling elsewhere). Any other runtime type hits the final else and throws IllegalArgumentException(String.format("Unsupported type %s", value.getClass())). The marshalled value protocol is intentionally minimal.

Source

Thrown at compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/BinaryOutput.java:303

            writeByte(CHAR);
            writeChar((char) value);
        } else if (value instanceof Integer) {
            writeByte(INT);
            writeInt((int) value);
        } else if (value instanceof Long) {
            writeByte(LONG);
            writeLong((long) value);
        } else if (value instanceof Float) {
            writeByte(FLOAT);
            writeFloat((float) value);
        } else if (value instanceof Double) {
            writeByte(DOUBLE);
            writeDouble((double) value);
        } else if (value instanceof String) {
            writeByte(STRING);
            writeUTF((String) value);
        } else {
            throw new IllegalArgumentException(String.format("Unsupported type %s", value.getClass()));
        }
    }

    /**
     * Writes {@code len} bytes from the boolean {@code array} starting at offset {@code off}. The
     * value {@code true} is written as the value {@code (byte)1}, the value {@code false} is
     * written as the value {@code (byte)0}. The buffer position is incremented by {@code len}.
     */
    public final void write(boolean[] array, int off, int len) {
        ensureBufferSize(0, len);
        for (int i = 0, j = 0; i < len; i++, j++) {
            tempDecodingBuffer[j] = (byte) (array[off + i] ? 1 : 0);
        }
        write(tempDecodingBuffer, 0, len);
    }

    /**
     * Writes {@code len} shorts from the {@code array} starting at offset {@code off}. The buffer

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Convert the value to a supported primitive/String (or a handle) before writeValue.
  2. Whitelist types at the call site with explicit instanceof branches mirroring writeValue's own dispatch.
  3. Fail fast in your API: validate value types before entering the marshalling layer rather than relying on its terminal exception.
  4. If you control the protocol, add a new tag on both BinaryOutput and BinaryInput sides consistently.

Example fix

// before
out.writeValue(maybeAnything);
// after (explicit supported-type dispatch)
if (v instanceof String s) out.writeValue(s);
else if (v instanceof Integer i) out.writeValue(i);
else throw new IllegalArgumentException("pre-validated: unsupported " + v.getClass());
Defensive patterns

Strategy: type-guard

Validate before calling

static boolean isMarshalableValue(Object v) {
    return v == null || v instanceof Boolean || v instanceof Byte || v instanceof Short
        || v instanceof Integer || v instanceof Long || v instanceof Float
        || v instanceof Double || v instanceof String;
}

Type guard

static boolean isMarshalableValue(Object v) {
    return v == null || v instanceof Boolean || v instanceof Byte || v instanceof Short
        || v instanceof Integer || v instanceof Long || v instanceof Float
        || v instanceof Double || v instanceof String;
}

Try / catch

try {
    out.writeValue(v);
} catch (IllegalArgumentException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("Unsupported type")) {
        // convert v to String/primitive or obtain an object handle instead
    }
}

Prevention

When it happens

Trigger: Calling writeValue with an arbitrary object (e.g. a custom record, enum, Object holding a Class reference, or a boxed type outside the supported set such as Character/BigDecimal) that was not converted beforehand.

Common situations: Generic code path where an unexpected boxed value trickles into the marshalling layer; adding a new value kind to a protocol without extending both writer and reader; null-handling assumptions that route non-null unknown objects into writeValue.

Related errors


AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14). Data as JSON: /api/errors/b99f41cf3d797dbd. Report an issue: GitHub.