{"record":{"id":"7ae0d42d87014d70","repo":"oracle/graal","slug":"unsupported-type-value-s-value-type-s","errorCode":null,"errorMessage":"Unsupported type: Value: %s, Value type: %s","messagePattern":"Unsupported type: Value: (.+?), Value type: (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/util/TypedDataOutputStream.java","lineNumber":100,"sourceCode":"            this.writeByte('I');\n            this.writeInt((Integer) value);\n        } else if (valueClz == Long.class) {\n            this.writeByte('J');\n            this.writeLong((Long) value);\n        } else if (valueClz == Float.class) {\n            this.writeByte('F');\n            this.writeFloat((Float) value);\n        } else if (valueClz == Double.class) {\n            this.writeByte('D');\n            this.writeDouble((Double) value);\n        } else if (valueClz == String.class) {\n            this.writeByte('U');\n            this.writeStringValue((String) value);\n        } else if (valueClz.isEnum()) {\n            this.writeByte('U');\n            this.writeStringValue(((Enum<?>) value).name());\n        } else {\n            throw new IllegalArgumentException(String.format(\"Unsupported type: Value: %s, Value type: %s\", value, valueClz));\n        }\n    }\n\n    protected void writeStringValue(String value) throws IOException {\n        byte[] bytes = value.getBytes(StandardCharsets.UTF_8);\n        this.writeInt(bytes.length);\n        this.write(bytes);\n    }\n}\n","sourceCodeStart":82,"sourceCodeEnd":110,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/util/TypedDataOutputStream.java#L82-L110","documentation":"IllegalArgumentException from TypedDataOutputStream.writeTypedValue: the value's class is not one of the supported cases (Boolean, Character, Integer, Long, Float, Double, String, enum, byte[] as implied by the type-tag scheme — 'F','D','U', etc.). The stream is a minimal, versioned serialization format for option/config values, so anything outside the whitelist is rejected at write time with the value and its class in the message.","triggerScenarios":"Calling writeTypedValue(value) (directly or via OptionsEncoder.encode) with e.g. Short, BigDecimal, java.net.URL, List, or a non-enum POJO — valueClz matches none of the if-chains and falls through to the throw.","commonSituations":"Extending an option map with a new value type without extending the codec; passing boxed Short or BigDecimal values that silently worked with other serializers (DataOutputStream) but not this one; enums are fine but records/classes named like enums are not.","solutions":["Convert the value to a supported type before writing: String, Integer, Long, Float, Double, Boolean, Character, byte[], or a Java enum (enums are stored by name()).","If the type must be first-class, add a new tag branch to writeTypedValue and the matching readTypedValue branch, keeping tags stable.","For Short values, widen to Integer explicitly to avoid surprises on the read side.","Add a unit test that round-trips every value type you intend to store."],"exampleFix":"// before\nout.writeTypedValue(Short.valueOf((short) 3)); // throws\n\n// after\nout.writeTypedValue(3); // store as Integer","handlingStrategy":"type-guard","validationCode":"static Object toTypedStreamValue(Object v) {\n    if (v instanceof Short s) return (int) s;   // widen\n    if (v instanceof Byte b) return (int) b;\n    if (v instanceof Number n && !(v instanceof Integer || v instanceof Long\n            || v instanceof Float || v instanceof Double)) return n.toString();\n    if (v != null && !(v instanceof Boolean || v instanceof Character || v instanceof String\n            || v instanceof byte[] || v.getClass().isEnum()\n            || v instanceof Integer || v instanceof Long || v instanceof Float || v instanceof Double)) {\n        return String.valueOf(v);\n    }\n    return v;\n}","typeGuard":"static boolean isSupportedTypedValue(Object v) {\n    if (v == null) return true;\n    Class<?> c = v.getClass();\n    return c == Boolean.class || c == Character.class || c == Integer.class\n        || c == Long.class || c == Float.class || c == Double.class\n        || c == String.class || c.isEnum();\n}","tryCatchPattern":"try {\n    out.writeTypedValue(v);\n} catch (IllegalArgumentException e) {\n    throw new ConfigException(\"unsupported option value type: \" + e.getMessage(), e);\n}","preventionTips":["Canonicalize all option values to the supported set at the point they enter the map.","Never add a new option value type without extending both writeTypedValue and readTypedValue symmetrically.","Unit-test the full value-type whitelist on every codec change."],"tags":["serialization","type-whitelist","illegal-argument","options"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}