apache/druid · error · IllegalArgumentException
Value [%s] is not valid for property [%s], expected type [%s
Error message
Value [%s] is not valid for property [%s], expected type [%s]
What it means
Thrown by CatalogUtils.safeCast when a catalog table property value exists but cannot be cast to the expected type via type.cast(value), i.e. ClassCastException. It reports the offending value, property key, and expected type name so the misconfigured table definition can be corrected.
Source
Thrown at server/src/main/java/org/apache/druid/catalog/model/CatalogUtils.java:110
*/
public static List<String> stringToList(String value)
{
if (value == null) {
return null;
}
return Arrays.asList(value.split(",\\s*"));
}
public static <T> T safeCast(Object value, Class<T> type, String key)
{
if (value == null) {
return null;
}
try {
return type.cast(value);
}
catch (ClassCastException e) {
throw new IAE("Value [%s] is not valid for property [%s], expected type [%s]",
value,
key,
type.getSimpleName()
);
}
}
public static <T> T safeGet(Map<String, Object> map, String key, Class<T> type)
{
return safeCast(map.get(key), type, key);
}
public static long getLong(Map<String, Object> map, String key)
{
Object value = map.get(key);
if (value == null) {
return 0;
}View on GitHub (pinned to 9b90983fd2)
Solutions
- Correct the table property value to the expected type (e.g. unquoted number for Long, JSON array of strings for string arrays)
- Inspect the persisted table definition and compare each property against the TableDefn schema
- If updating programmatically, wrap numbers in the exact expected boxed type (Long, not Integer)
Example fix
// before
{"targetLoadOnly": "true"}
// after
{"targetLoadOnly": true} Defensive patterns
Strategy: type-guard
Validate before calling
if (value instanceof String && expected == Long.class) {
// pre-coerce or reject: "123" will fail cast
}
if (expected == List.class && !(value instanceof List)) {
throw new IllegalArgumentException("Property must be a JSON array");
} Type guard
static <T> boolean isAssignable(Object value, Class<T> type) {
return type.isInstance(value);
}
// usage: if (!isAssignable(props.get(key), Long.class)) fix before safeGet; Try / catch
try {
Long v = CatalogUtils.safeGet(props, "someLong", Long.class);
} catch (IllegalArgumentException e) {
log.error("Bad property type: {}", e.getMessage());
} Prevention
- Store JSON-typed values (unquoted numbers, real arrays) in table properties
- Round-trip definitions through the object mapper to normalize types
- Watch for Integer vs Long when building properties programmatically
When it happens
Trigger: Calling safeGet/getLong/getStringArray (or safeCast directly) on a table property whose stored value type differs from the expected one - e.g. a string '123' where a Long is expected, a scalar where List<String> is expected, or JSON deserialization yielding a different concrete type.
Common situations: Hand-edited catalog JSON where numbers are quoted as strings, schema changes between Druid versions altering a property's type, programmatic updates writing Integer where Long is required (Integer cannot be cast to Long).
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
- [%s] column must have type [%s] or no type. Found [%s]
- An external S3 table with a format must also provide the cor
- Provide either the %s property, or one of the S3 input sourc
- The %s property cannot be provided when the %s property is s
- S3 external table defines the %s property. The table functio
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/74c88fe67424d9b2.
Report an issue: GitHub.