clockworklabs/SpacetimeDB · error · TypeError

Cannot convert ${typeof value} to ${what}: expected bigint,

Error message

Cannot convert ${typeof value} to ${what}: expected bigint, integer number, or decimal string

What it means

coerceToBigInt is the strict front door for id/time constructors (Uuid, Identity, ConnectionId, Timestamp, TimeDuration). Unlike bare BigInt() - which would silently turn true into 1n, [42] into 42n, and '' into 0n - it accepts only bigint, number, or a non-empty string, and throws TypeError for everything else so malformed payloads fail early instead of becoming valid-looking ids.

Source

Thrown at crates/bindings-typescript/src/lib/util.ts:115

}

/**
 * Coerces a value that should be a `bigint` — but may arrive as a `number`
 * or decimal string after passing through JSON — into a `bigint`.
 *
 * Every other type is rejected up front: bare `BigInt()` would silently
 * accept booleans (`true` → `1n`), arrays (`[42]` → `42n`) and empty
 * strings (`'' ` → `0n`), turning malformed payloads into valid-looking
 * ids instead of failing early.
 *
 * @param value The value to coerce
 * @param what Type name used in the error message (e.g. `'ConnectionId'`)
 */
export function coerceToBigInt(value: unknown, what: string): bigint {
  if (typeof value === 'bigint') return value;
  if (typeof value === 'number') return BigInt(value);
  if (typeof value === 'string' && value.trim() !== '') return BigInt(value);
  throw new TypeError(
    `Cannot convert ${typeof value} to ${what}: expected bigint, integer number, or decimal string`
  );
}

/**
 * Converts a string to PascalCase (UpperCamelCase).
 * @param str The string to convert
 * @returns The converted string
 */
export function toPascalCase(s: string): string {
  const str = toCamelCase(s);
  return str.charAt(0).toUpperCase() + str.slice(1);
}

/**
 * Type safe conversion from a string like "some_identifier-name" to "someIdentifierName".
 * @param str The string to convert
 * @returns The converted string

View on GitHub (pinned to 524b4487d9)

Solutions

  1. Check the field exists and is a bigint, number, or non-empty decimal string before constructing
  2. Fix the producer to send decimal strings for 128/256-bit ids (JSON cannot carry bigint precisely)
  3. Reject or default the whole record early when the id field is optional, instead of constructing with garbage

Example fix

// before
const id = new Uuid(payload.userId); // payload.userId === undefined -> TypeError

// after
const raw = payload.userId;
if (typeof raw !== 'bigint' && typeof raw !== 'number' && !(typeof raw === 'string' && raw.trim() !== '')) {
  throw new TypeError(`bad userId in payload: ${JSON.stringify(payload)}`);
}
const id = new Uuid(raw as bigint | number | string);
Defensive patterns

Strategy: type-guard

Validate before calling

function isCoercibleToBigInt(v: unknown): boolean {
  if (typeof v === 'bigint' || typeof v === 'number') return true;
  if (typeof v === 'string') return v.trim() !== '';
  return false;
}
// if (!isCoercibleToBigInt(payload.userId)) throw new TypeError('bad id field');

Type guard

type BigIntCoercible = bigint | number | string;
function isBigIntCoercible(v: unknown): v is BigIntCoercible {
  if (typeof v === 'bigint' || typeof v === 'number') return true;
  if (typeof v === 'string') return v.trim() !== '';
  return false;
}

Prevention

When it happens

Trigger: new Uuid(json.userId), new ConnectionId(wsMsg.connectionId), new Timestamp(payload.ts), or new Identity(...) where the field is undefined, null, a boolean, an object, or '' - typical right after JSON.parse of a payload with the wrong shape or missing keys.

Common situations: API/WebSocket payloads whose field names changed or which are optional; environment variables read as empty strings; schema changes where an id moved from string to object; numbers that lost precision through JSON.

Related errors


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