{"record":{"id":"b1a9753608d79890","repo":"clockworklabs/SpacetimeDB","slug":"invalid-hex-uuid","errorCode":null,"errorMessage":"Invalid hex UUID","messagePattern":"Invalid hex UUID","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"crates/bindings-typescript/src/lib/uuid.ts","lineNumber":225,"sourceCode":"\n  /**\n   * Parse a UUID from a string representation.\n   *\n   * @param s - UUID string\n   * @returns Parsed UUID\n   * @throws {Error} If the string is not a valid UUID\n   *\n   * @example\n   * ```ts\n   * const s = \"01888d6e-5c00-7000-8000-000000000000\";\n   * const uuid = Uuid.parse(s);\n   *\n   * console.assert(uuid.toString() === s);\n   * ```\n   */\n  static parse(s: string): Uuid {\n    const hex = s.replace(/-/g, '');\n    if (hex.length !== 32) throw new Error('Invalid hex UUID');\n\n    let v = 0n;\n    for (let i = 0; i < 32; i += 2) {\n      v = (v << 8n) | BigInt(parseInt(hex.slice(i, i + 2), 16));\n    }\n    return new Uuid(v);\n  }\n\n  /** Convert to hex string without a 0x prefix. */\n  toHexString(): string {\n    return u128ToHexString(this.asBigInt());\n  }\n\n  /** Convert to string (hyphenated form). */\n  toString(): string {\n    const hex = this.toHexString();\n\n    // Format as 8-4-4-4-12","sourceCodeStart":207,"sourceCodeEnd":243,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/524b4487d949b61a07d4f39c862d1290259dfd20/crates/bindings-typescript/src/lib/uuid.ts#L207-L243","documentation":"Uuid.parse strips every '-' character and then requires exactly 32 remaining characters. The error fires on wrong length (not on non-hex characters: a 32-character string with invalid hex slips past this check and fails later inside BigInt parsing). Dashes are optional but the total hex digit count must be 32.","triggerScenarios":"Parsing strings such as '{01888d6e-5c00-7000-8000-000000000000}' (braces), 'urn:uuid:...' (URN prefix), a truncated UUID, a UUID with whitespace, or one with extra/missing hex digits.","commonSituations":"Copying a UUID from logs together with quotes or braces; receiving ids wrapped by another system (PostgreSQL URN output, JSON with padding); a typo dropping a character; concatenated strings.","solutions":["Normalize before parsing: trim whitespace and strip '{', '}' and any 'urn:uuid:' prefix","Validate with a UUID regex before calling Uuid.parse","If the string came from Uuid.toString(), pass it through unchanged - it is already 8-4-4-4-12"],"exampleFix":"// before\nconst uuid = Uuid.parse('{01888d6e-5c00-7000-8000-000000000000}'); // throws\n\n// after\nconst s = '{01888d6e-5c00-7000-8000-000000000000}'.replace(/[{}]/g, '').replace(/^urn:uuid:/i, '').trim();\nconst uuid = UUID_RE.test(s) ? Uuid.parse(s) : null;","handlingStrategy":"type-guard","validationCode":"const s = raw.replace(/[{}\\s]/g, '').replace(/^urn:uuid:/i, '');\nif (!isUuidString(s)) throw new TypeError('not a UUID string');\nconst uuid = Uuid.parse(s);","typeGuard":"const UUID_RE = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;\nfunction isUuidString(s: unknown): s is string {\n  return typeof s === 'string' && (UUID_RE.test(s) || /^[0-9a-fA-F]{32}$/.test(s));\n}","tryCatchPattern":"try {\n  const id = Uuid.parse(input);\n} catch (e) {\n  if (e instanceof Error && e.message === 'Invalid hex UUID') {\n    // treat as malformed external input: reject or skip the record\n  } else throw e;\n}","preventionTips":["Normalize external ids (trim, strip braces/URN prefix) before parsing","Validate with a regex at the API boundary instead of relying on parse's length check"],"tags":["uuid","parsing","validation","typescript"],"backgroundTag":"uuid-parse-error","analyzedSha":"524b4487d949b61a07d4f39c862d1290259dfd20","analyzedAt":"2026-08-16T23:58:54.611Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}