{"record":{"id":"79b0222801608abe","repo":"clockworklabs/SpacetimeDB","slug":"only-btree-indexes-are-supported-in-tablecacheimpl","errorCode":null,"errorMessage":"Only btree indexes are supported in TableCacheImpl","messagePattern":"Only btree indexes are supported in TableCacheImpl","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"crates/bindings-typescript/src/sdk/table_cache.ts","lineNumber":120,"sourceCode":"    }\n  }\n\n  // TODO: this just scans the whole table; we should build proper index structures\n  #makeReadonlyIndex<\n    I extends TableDefForTableName<\n      RemoteModule,\n      TableName\n    >['resolvedIndexes'][number],\n  >(\n    tableDef: TableDefForTableName<RemoteModule, TableName>,\n    idx: I\n  ): ReadonlyIndex<TableDefForTableName<RemoteModule, TableName>, I> {\n    type TableDef = TableDefForTableName<RemoteModule, TableName>;\n    type Row = Prettify<RowType<TableDef>>;\n\n    // We do not yet support non-btree indexes\n    if (idx.algorithm !== 'btree') {\n      throw new Error('Only btree indexes are supported in TableCacheImpl');\n    }\n\n    const columns = idx.columns;\n\n    // Extract the tuple key for this btree index (column order preserved)\n    const getKey = (row: Row): readonly unknown[] =>\n      columns.map(c => (row as Record<string, unknown>)[c]);\n\n    // The server’s ranged scan fixes all prefix cols to equality and applies\n    // the bound only to the *last* term. We mirror that.\n    //\n    // rangeArg for multi-col index is:\n    //   [...prefixEqualValues, (lastTerm | Range<lastTerm>)]\n    //\n    // If only one element is provided, it’s the last term (scalar or Range).\n    const matchRange = (row: Row, rangeArg: any): boolean => {\n      const key = getKey(row);\n","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/524b4487d949b61a07d4f39c862d1290259dfd20/crates/bindings-typescript/src/sdk/table_cache.ts#L102-L138","documentation":"TableCacheImpl's index read path mirrors the server's btree ranged-scan semantics (prefix columns fixed to equality, range bound on the last term). Only idx.algorithm === 'btree' can be served this way, so requesting a cached index view for any other algorithm (e.g. hash) throws with an explicit 'not yet supported' comment in the source.","triggerScenarios":"A module schema declares a non-btree index (e.g. #[index(hash)] on a column) and client code accesses that index through the TableCache index API.","commonSituations":"Porting a module that used hash indexes for point lookups; a module upgrade adds a hash index and the generated bindings now expose it to the cache; following older examples/docs that assumed index-agnostic access.","solutions":["Change the module schema to use a btree index for columns you read through the client cache","For point lookups on hash-indexed columns, query with a WHERE clause server-side instead of the cache index API","Check for SDK updates - non-btree index support in TableCacheImpl is on the roadmap per the source comment"],"exampleFix":"// module (Rust) - before\n#[spacetimedb::table(name = user)]\npub struct User {\n  #[primary_key]\n  #[spacetimedb(index = hash)] // client cache throws on this\n  pub email: String,\n}\n\n// after\n#[spacetimedb::table(name = user)]\npub struct User {\n  #[primary_key]\n  #[spacetimedb(index = btree)]\n  pub email: String,\n}","handlingStrategy":"validation","validationCode":"const idx = tableDef.resolvedIndexes.find(i => i.accessorName === wanted);\nif (idx && idx.algorithm !== 'btree') {\n  // skip the cache index API; use a SQL WHERE query or full row iteration\n}","typeGuard":"function isBtreeIndex(idx: { algorithm: string }): boolean {\n  return idx.algorithm === 'btree';\n}","tryCatchPattern":null,"preventionTips":["Stick to btree indexes in module schemas you plan to read via the client cache","Keep point lookups on hash indexes server-side (subscription WHERE clauses)"],"tags":["index","btree","schema","table-cache","typescript"],"backgroundTag":"unsupported-index-type","analyzedSha":"524b4487d949b61a07d4f39c862d1290259dfd20","analyzedAt":"2026-08-16T23:58:54.611Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}