clockworklabs/SpacetimeDB · error · Error
Invalid hex UUID
Error message
Invalid hex UUID
What it means
Uuid.parse strips every '-' from the input and then requires the remainder to be exactly 32 characters. The 'Invalid hex UUID' error is this dash-stripped length check: wrong digit count, brace/URN wrappers, 0x prefixes, or extra characters all change the length and fail. Note the parser checks length, not character legality, so do not rely on it to validate hex.
Solutions
- Validate with a canonical UUID regex before parsing (see type guard)
- Normalize the input first: trim whitespace, strip surrounding braces and 'urn:uuid:' prefixes
- Only call parse on values produced by Uuid.toString() or a known UUID source
Example fix
// before const id = Uuid.parse(rawUserInput); // may throw // after const id = isUuidString(rawUserInput) ? Uuid.parse(rawUserInput) : fallbackForInvalidId(rawUserInput);
Defensive patterns
Strategy: type-guard
Validate before calling
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}$/;
if (!UUID_RE.test(candidate)) {
throw new Error(`not a canonical UUID: ${candidate}`);
}
const id = Uuid.parse(candidate); Type guard
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}$/;
function isUuidString(s: unknown): s is string {
return typeof s === 'string' && UUID_RE.test(s);
} Try / catch
try {
const id = Uuid.parse(candidate);
} catch (e) {
if (e instanceof Error && e.message === 'Invalid hex UUID') {
// treat as bad input: reject, re-prompt, or skip the record
}
throw e;
} Prevention
- Validate untrusted strings with the regex guard before parse; parse only checks dash-stripped length
- Normalize inputs: trim, strip '{', '}' and 'urn:uuid:' prefixes
- Round-trip your own IDs via Uuid.toString() so the format is always canonical
When it happens
Trigger: Uuid.parse('not-a-uuid'); Uuid.parse('01888d6e-5c00-7000-8000-0000000000') (31 hex digits after the 12 hex digits of the last group are short by one); strings like '{01888d6e-...}' or 'urn:uuid:...' that add non-hex characters; values with trailing whitespace or a 0x prefix.
Common situations: Forwarding user input, URL query params, or database columns straight into parse; mixing canonical hyphenated and compact 32-char formats; UUIDs received from other systems wrapped in braces or URN prefixes.
Related errors
- `fromCounterV7` requires `randomBytes.length == 4`
- `fromCounterV7` `timestamp` before unix epoch
- `fromCounterV7` uuid `counter` must be non-negative
- Invalid version string
- Unsupported UUID version
AI-assisted analysis of clockworklabs/SpacetimeDB@6dee26c6ef (2026-08-20).
Data as JSON: /api/errors/b1a9753608d79890.
Report an issue: GitHub.
Appendix: source
Thrown at crates/bindings-typescript/src/lib/uuid.ts:225
/**
* Parse a UUID from a string representation.
*
* @param s - UUID string
* @returns Parsed UUID
* @throws {Error} If the string is not a valid UUID
*
* @example
* ```ts
* const s = "01888d6e-5c00-7000-8000-000000000000";
* const uuid = Uuid.parse(s);
*
* console.assert(uuid.toString() === s);
* ```
*/
static parse(s: string): Uuid {
const hex = s.replace(/-/g, '');
if (hex.length !== 32) throw new Error('Invalid hex UUID');
let v = 0n;
for (let i = 0; i < 32; i += 2) {
v = (v << 8n) | BigInt(parseInt(hex.slice(i, i + 2), 16));
}
return new Uuid(v);
}
/** Convert to hex string without a 0x prefix. */
toHexString(): string {
return u128ToHexString(this.asBigInt());
}
/** Convert to string (hyphenated form). */
toString(): string {
const hex = this.toHexString();
// Format as 8-4-4-4-12View on GitHub (pinned to 6dee26c6ef)