apache/druid · error · QueryDriver.RequestError
Invalid parameter type:
Error message
Invalid parameter type:
What it means
translateParameter converts a gRPC QueryParameter's protobuf Value into a Druid SqlParameter. It handles STRING, and treats NULL_VALUE/VALUE_NOT_SET as null; any other value case (e.g. number, bool, array) hits the default branch and throws RequestError("Invalid parameter type: ..."), because the gRPC SQL interface only supports string-typed (VARCHAR) query parameters.
Source
Thrown at extensions-contrib/grpc-query/src/main/java/org/apache/druid/grpc/server/QueryDriver.java:374
}
return params;
}
private SqlParameter translateParameter(QueryParameter value)
{
switch (value.getValueCase()) {
case DOUBLEVALUE:
return new SqlParameter(SqlType.DOUBLE, value.getDoubleValue());
case LONGVALUE:
return new SqlParameter(SqlType.BIGINT, value.getLongValue());
case STRINGVALUE:
return new SqlParameter(SqlType.VARCHAR, value.getStringValue());
case NULLVALUE:
case VALUE_NOT_SET:
return null;
case ARRAYVALUE:
default:
throw new RequestError("Invalid parameter type: " + value.getValueCase().name());
}
}
/**
* Translate the column schema from the Druid internal form to the gRPC
* {@link ColumnSchema} form. Note that since the gRPC response returns the
* schema, none of the data formats include a header. This makes the data format
* simpler and cleaner.
*/
private Iterable<? extends ColumnSchema> encodeSqlColumns(SqlRowTransformer rowTransformer)
{
RelDataType rowType = rowTransformer.getRowType();
final RowSignature signature = RowSignatures.fromRelDataType(rowType.getFieldNames(), rowType);
List<ColumnSchema> cols = new ArrayList<>();
for (int i = 0; i < rowType.getFieldCount(); i++) {
ColumnSchema col = ColumnSchema.newBuilder()
.setName(signature.getColumnName(i))
.setSqlType(rowType.getFieldList().get(i).getType().getSqlTypeName().getName())View on GitHub (pinned to 9b90983fd2)
Solutions
- Wrap every parameter value as a StringValue in the gRPC request (e.g. Value.newBuilder().setStringValue("42")) and cast in SQL if needed.
- For truly NULL parameters, use NULL_VALUE or leave the value unset rather than a typed empty value.
- Update the calling code so numbers/booleans are stringified before being placed into QueryParameter.
- If array parameters are needed, check the extension version for array support or restructure the SQL to avoid array parameters.
Example fix
// before
Value v = Value.newBuilder().setInt32Value(42).build();
// after
Value v = Value.newBuilder().setStringValue("42").build(); Defensive patterns
Strategy: type-guard
Validate before calling
// Guard parameter values before building the protobuf request
static boolean isSupportedParamValue(Object v) {
return v == null || v instanceof String; // only string/NULL parameters supported
} Type guard
boolean isStringValue(com.google.protobuf.Value v) {
return v.getKindCase() == com.google.protobuf.Value.KindCase.STRING_VALUE
|| v.getKindCase() == com.google.protobuf.Value.KindCase.NULL_VALUE
|| v.getKindCase() == com.google.protobuf.Value.KindCase.KIND_NOT_SET;
} Try / catch
try {
return stub.query(req);
} catch (StatusRuntimeException e) {
if (e.getStatus().getDescription() != null && e.getStatus().getDescription().startsWith("Invalid parameter type")) {
throw new IllegalArgumentException("Only VARCHAR (string) and NULL parameters are supported", e);
}
throw e;
} Prevention
- Always wrap parameters in Value.newBuilder().setStringValue(...) on the client.
- Convert numbers/booleans to strings in client code before binding parameters.
- Add a unit test that builds every query's parameter list through one helper that enforces string values.
- Cast inside SQL (CAST(? AS BIGINT)) rather than sending typed protobuf values.
When it happens
Trigger: Submitting a gRPC SQL query whose QueryParameter.value is set to a non-string oneof case — e.g. Int32Value, BoolValue, Struct, or ArrayValue — instead of a StringValue (or leaving the case as something other than NULLVALUE/VALUE_NOT_SET).
Common situations: Client SDK auto-converts a language number/boolean into a typed protobuf Value instead of wrapping it in a string; hand-built protobuf requests that set a typed field; code generated against a newer request schema passing arrays.
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
- Unsupported query result format:
- The Protobuf class [%s] is not known. Is your protobuf jar o
- The class [%s] is not a Protobuf
- Cannot translate sqlTypeName[%s] to Druid type for field[%s]
- Unauthorized
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/cf56496f717d4b70.
Report an issue: GitHub.