clockworklabs/SpacetimeDB · error · TypeError

Index '${idx.sourceName ?? '<unknown>'}' on table '${tableDe

Error message

Index '${idx.sourceName ?? '<unknown>'}' on table '${tableDef.sourceName}' is missing accessor name

What it means

When schema.ts converts the host-facing RawTableDef into the client-side TableToSchema, it builds fully-resolved runtime index metadata and requires every tableDef.indexes[i].accessorName to be a non-empty string, else it throws a TypeError naming the index and table. Because this metadata is produced by the host toolchain, a missing accessorName almost always means the defs came from an older or mismatched producer.

Source

Thrown at crates/bindings-typescript/src/lib/schema.ts:117

  AccName extends string,
  const T extends UntypedTableSchema,
>(
  accName: AccName,
  schema: T,
  tableDef: RawTableDefV10
): TableToSchema<AccName, T> {
  const getColName = (i: number) =>
    schema.rowType.algebraicType.value.elements[i].name;

  type AllowedCol = keyof T['rowType']['row'] & string;
  // Build fully-resolved runtime index metadata from the host-facing RawTableDef.
  // This is intentionally separate from `schema.idxs`, which keeps the original
  // user-declared `IndexOpts` shape for type-level inference.
  const resolvedIndexes: UntypedIndex<AllowedCol>[] = tableDef.indexes.map(
    idx => {
      const accessorName = idx.accessorName;
      if (typeof accessorName !== 'string' || accessorName.length === 0) {
        throw new TypeError(
          `Index '${idx.sourceName ?? '<unknown>'}' on table '${tableDef.sourceName}' is missing accessor name`
        );
      }

      const columnIds =
        idx.algorithm.tag === 'Direct'
          ? [idx.algorithm.value]
          : idx.algorithm.value;

      const unique = tableDef.constraints.some(
        c =>
          c.data.tag === 'Unique' &&
          c.data.value.columns.every(col => columnIds.includes(col))
      );

      const algorithm = (
        {
          BTree: 'btree',

View on GitHub (pinned to 524b4487d9)

Solutions

  1. Align versions: upgrade the spacetimedb toolchain/server and the TS bindings to releases that both emit and require accessorName
  2. If you construct RawTableDef yourself (tests, fixtures), set a non-empty accessorName on every index
  3. If the host genuinely omits the field on current versions, report it upstream with the def JSON

Example fix

// before
const tableDef: RawTableDef = JSON.parse(fixtureJson); // indexes[].accessorName missing -> throws

// after
for (const idx of tableDef.indexes) {
  if (typeof idx.accessorName !== 'string' || idx.accessorName.length === 0) {
    idx.accessorName = idx.sourceName!; // backfill before conversion
  }
}
Defensive patterns

Strategy: validation

Validate before calling

function validateRawTableDefIndexes(tableDef: { indexes: Array<{ sourceName?: string; accessorName?: unknown }>; sourceName: string }): void {
  for (const idx of tableDef.indexes) {
    if (typeof idx.accessorName !== 'string' || idx.accessorName.length === 0) {
      throw new Error(
        `tableDef for '${tableDef.sourceName}': index '${idx.sourceName ?? '<unknown>'}' lacks accessorName - host/bindings version mismatch?`
      );
    }
  }
}

Prevention

When it happens

Trigger: Converting a RawTableDef whose indexes entries lack accessorName - typically a def emitted by an older spacetimedb host/CLI than the TS bindings expect, or a hand-assembled def in tests.

Common situations: Version skew between the SpacetimeDB server/tools that generated the table def and the @clockworklabs bindings that consume it; test fixtures hand-rolling RawTableDef JSON without the full index metadata.

Related errors


AI-assisted analysis of clockworklabs/SpacetimeDB@524b4487d9 (2026-08-16). Data as JSON: /api/errors/1d46333e787c9c81. Report an issue: GitHub.