apache/druid · error · UnsupportedOperationException
Table decoding not supported for
Error message
Table decoding not supported for %s
What it means
VSizeLongSerde long-column encodings that do not implement table-based decoding throw this UnsupportedOperationException from the default ColumnarLongsSupplier.getLongMulti/getTable default method. It means the requested vectorized 'lookup and replace' decode path is unavailable for the concrete LongValueEncoding in use. It is a 'this encoding doesn't support this operation' guard, not data corruption.
Solutions
- Verify the segment's long column encoding; re-ingest or re-index the segment with a current Druid version so the column is written with table-decoding-capable encoding
- Fall back to the non-table decode path: catch UOE and re-run the query with vectorization disabled (set druid.query.vectorize=false or use non-vectorized selectors)
- Upgrade Druid on the node serving the segment so the encoding implements getTable
Example fix
// before
encoding.getTable(out, outPosition, startIndex, length, table);
// after
try {
encoding.getTable(out, outPosition, startIndex, length, table);
} catch (UnsupportedOperationException e) {
encoding.fill(out, outPosition, startIndex, length); // non-table fallback
} Defensive patterns
Strategy: try-catch
Validate before calling
// Java: check if the encoding supports table decoding before use
if (encoding.getClass().getSimpleName().equals("LongEncodingReader")) { /* fall back */ } Type guard
boolean supportsTableDecode(ColumnarLongsSerializer encoding) {
try { encoding.getClass().getMethod("getTable", long[].class, int.class, int.class, int.class, long[].class); return true; }
catch (NoSuchMethodException e) { return false; }
} Try / catch
try {
encoding.getTable(out, outPosition, startIndex, length, table);
} catch (UnsupportedOperationException e) {
// fall back to non-table decode
encoding.fill(out, outPosition, startIndex, length);
} Prevention
- Re-index old segments so long columns use table-decoding-capable encodings
- Keep historical nodes on a Druid version compatible with the segments they serve
- Test vectorized queries against oldest retained segments before rolling out query features
When it happens
Trigger: Calling getTable(long[], int, int, int, long[]) (or vectorized table-based decoding via a LongValueEncoding that only overrides fill/forEach) on a column written with an encoding that lacks table decode support, e.g. a VSizeLongSerde v1-encoded column without table-decoding support.
Common situations: Running vectorized group-by/search queries over older segments whose long column encoding predates table decoding support; mixing Druid versions where a broker routes vectorized work to a historical with older segment files.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- attempt to get boolean[] null vector from string[] only…
- attempt to get double[] from string[] only scalar binding
- attempt to get long[] from string[] only scalar binding
- Not enough space for aggregators, needed [%,d] bytes but…
- Possible data truncation, param
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/113eed40ab12f135.
Report an issue: GitHub.
Appendix: source
Thrown at processing/src/main/java/org/apache/druid/segment/data/VSizeLongSerde.java:464
for (int i = 0; i < length; i++) {
int index = indexes[outPosition + i] - indexOffset;
if (index >= limit) {
return i;
}
out[outPosition + i] = base + get(index);
}
return length;
}
/**
* Unpack a contiguous vector of long values at the specified start index of length and lookup and replace stored
* values based on their index in the supplied value lookup 'table'
*/
default void getTable(long[] out, int outPosition, int startIndex, int length, long[] table)
{
throw new UOE("Table decoding not supported for %s", this.getClass().getSimpleName());
}
/**
* Unpack a contiguous vector of long values at the specified indexes and lookup and replace stored values based on
* their index in the supplied value lookup 'table'
*/
default int getTable(
long[] out,
int outPosition,
int[] indexes,
int length,
int indexOffset,
int limit,
long[] table
)
{
for (int i = 0; i < length; i++) {
int index = indexes[outPosition + i] - indexOffset;View on GitHub (pinned to 9b90983fd2)