{"record":{"id":"19e7794ade9db4f8","repo":"apache/druid","slug":"caching-is-not-supported-check-iscacheable-befo","errorCode":null,"errorMessage":"Caching is not supported. Check `isCacheable` before calling computeCacheKey","messagePattern":"Caching is not supported\\. Check `isCacheable` before calling computeCacheKey","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/segment/join/table/IndexedTable.java","lineNumber":103,"sourceCode":"   * instead.\n   */\n  @Nullable\n  default ColumnSelectorFactory makeColumnSelectorFactory(ReadableOffset offset, Closer closer)\n  {\n    return null;\n  }\n\n  /**\n   * Computes a {@code byte[]} key for the table that can be used for computing cache keys for join operations.\n   * see {@link org.apache.druid.segment.join.JoinableFactory#computeJoinCacheKey}\n   *\n   * @return the byte array for cache key\n   *\n   * @throws {@link IAE} if caching is not supported\n   */\n  default byte[] computeCacheKey()\n  {\n    throw new IAE(\"Caching is not supported. Check `isCacheable` before calling computeCacheKey\");\n  }\n\n  /**\n   * Returns whether this indexed table can be cached for the join operations\n   */\n  default boolean isCacheable()\n  {\n    return false;\n  }\n\n  /**\n   * Indexes support fast lookups on key columns.\n   */\n  interface Index\n  {\n    int NOT_FOUND = -1;\n\n    /**","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/segment/join/table/IndexedTable.java#L85-L121","documentation":"IndexedTable's default computeCacheKey() throws because not every joinable table supports caching. The table contract requires callers to check isCacheable() first; calling computeCacheKey() on a non-cacheable table is a programming error, so the default implementation fails fast with IllegalArgumentException.","triggerScenarios":"Calling computeCacheKey() directly on an IndexedTable implementation that does not override it (or whose isCacheable() returns false), e.g. when building a cache key for a join query against a non-cacheable broadcast table.","commonSituations":"Custom IndexedTable implementations that rely on the default methods while enabling query caching; internal code paths that construct cache keys for join queries without the isCacheable() guard; table providers that report cache keys for tables lacking key columns.","solutions":["Call table.isCacheable() before invoking computeCacheKey() and skip caching when false","Override computeCacheKey() and isCacheable() consistently in your IndexedTable implementation","If the table should be cacheable, ensure it has valid key columns and a cache key configured at construction"],"exampleFix":"// before\nbyte[] cacheKey = table.computeCacheKey();\n// after\nif (table.isCacheable()) {\n  byte[] cacheKey = table.computeCacheKey();\n} else {\n  // skip caching for this table\n}","handlingStrategy":"validation","validationCode":"if (table.isCacheable()) { byte[] key = table.computeCacheKey(); }","typeGuard":"boolean cacheable = table.isCacheable();","tryCatchPattern":null,"preventionTips":["Always gate cache-key computation behind isCacheable()","Override both isCacheable and computeCacheKey together in custom tables"],"tags":["java","join","cache-key","illegal-argument"],"backgroundTag":"unsupported-operation","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}