{"record":{"id":"37df46eb62abb8a3","repo":"clockworklabs/SpacetimeDB","slug":"cannot-convert-typeof-value-to-what-expecte","errorCode":null,"errorMessage":"Cannot convert ${typeof value} to ${what}: expected bigint, integer number, or decimal string","messagePattern":"Cannot convert (.+?) to (.+?): expected bigint, integer number, or decimal string","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"crates/bindings-typescript/src/lib/util.ts","lineNumber":115,"sourceCode":"}\n\n/**\n * Coerces a value that should be a `bigint` — but may arrive as a `number`\n * or decimal string after passing through JSON — into a `bigint`.\n *\n * Every other type is rejected up front: bare `BigInt()` would silently\n * accept booleans (`true` → `1n`), arrays (`[42]` → `42n`) and empty\n * strings (`'' ` → `0n`), turning malformed payloads into valid-looking\n * ids instead of failing early.\n *\n * @param value The value to coerce\n * @param what Type name used in the error message (e.g. `'ConnectionId'`)\n */\nexport function coerceToBigInt(value: unknown, what: string): bigint {\n  if (typeof value === 'bigint') return value;\n  if (typeof value === 'number') return BigInt(value);\n  if (typeof value === 'string' && value.trim() !== '') return BigInt(value);\n  throw new TypeError(\n    `Cannot convert ${typeof value} to ${what}: expected bigint, integer number, or decimal string`\n  );\n}\n\n/**\n * Converts a string to PascalCase (UpperCamelCase).\n * @param str The string to convert\n * @returns The converted string\n */\nexport function toPascalCase(s: string): string {\n  const str = toCamelCase(s);\n  return str.charAt(0).toUpperCase() + str.slice(1);\n}\n\n/**\n * Type safe conversion from a string like \"some_identifier-name\" to \"someIdentifierName\".\n * @param str The string to convert\n * @returns The converted string","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/524b4487d949b61a07d4f39c862d1290259dfd20/crates/bindings-typescript/src/lib/util.ts#L97-L133","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check the field exists and is a bigint, number, or non-empty decimal string before constructing","Fix the producer to send decimal strings for 128/256-bit ids (JSON cannot carry bigint precisely)","Reject or default the whole record early when the id field is optional, instead of constructing with garbage"],"exampleFix":"// before\nconst id = new Uuid(payload.userId); // payload.userId === undefined -> TypeError\n\n// after\nconst raw = payload.userId;\nif (typeof raw !== 'bigint' && typeof raw !== 'number' && !(typeof raw === 'string' && raw.trim() !== '')) {\n  throw new TypeError(`bad userId in payload: ${JSON.stringify(payload)}`);\n}\nconst id = new Uuid(raw as bigint | number | string);","handlingStrategy":"type-guard","validationCode":"function isCoercibleToBigInt(v: unknown): boolean {\n  if (typeof v === 'bigint' || typeof v === 'number') return true;\n  if (typeof v === 'string') return v.trim() !== '';\n  return false;\n}\n// if (!isCoercibleToBigInt(payload.userId)) throw new TypeError('bad id field');","typeGuard":"type BigIntCoercible = bigint | number | string;\nfunction isBigIntCoercible(v: unknown): v is BigIntCoercible {\n  if (typeof v === 'bigint' || typeof v === 'number') return true;\n  if (typeof v === 'string') return v.trim() !== '';\n  return false;\n}","tryCatchPattern":null,"preventionTips":["Validate id/timestamp fields at the JSON boundary before constructing Uuid/Identity/ConnectionId/Timestamp","Have producers send 128/256-bit ids as decimal strings, never JSON numbers","Treat booleans/objects/empty strings as payload bugs - never coerce them silently"],"tags":["coercion","bigint","validation","typescript","json"],"backgroundTag":"invalid-numeric-coercion","analyzedSha":"524b4487d949b61a07d4f39c862d1290259dfd20","analyzedAt":"2026-08-16T23:58:54.611Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}