BloopAI/vibe-kanban · error
Invalid enrollment ID.
Error message
Invalid enrollment ID.
What it means
uuidToBytes converts a hyphen-stripped UUID hex string to 16 bytes and throws if the resulting hex is not exactly 32 characters — i.e. the input is not a well-formed UUID. Reached via enrollmentIdBytes when building enrollment request payloads.
Source
Thrown at packages/web-core/src/shared/lib/relayPake.ts:267
['sign']
);
const signature = await crypto.subtle.sign('HMAC', key, toArrayBuffer(data));
return new Uint8Array(signature);
}
async function sha256(data: Uint8Array): Promise<Uint8Array> {
const digest = await crypto.subtle.digest('SHA-256', toArrayBuffer(data));
return new Uint8Array(digest);
}
function toArrayBuffer(data: Uint8Array): ArrayBuffer {
return new Uint8Array(data).buffer;
}
function uuidToBytes(rawUuid: string): Uint8Array {
const hex = rawUuid.replace(/-/g, '');
if (hex.length !== 32) {
throw new Error('Invalid enrollment ID.');
}
const bytes = new Uint8Array(16);
for (let i = 0; i < 16; i += 1) {
const value = Number.parseInt(hex.slice(i * 2, i * 2 + 2), 16);
if (Number.isNaN(value)) {
throw new Error('Invalid enrollment ID.');
}
bytes[i] = value;
}
return bytes;
}
function bytesToBigIntLE(bytes: Uint8Array): bigint {
let value = 0n;
for (let i = bytes.length - 1; i >= 0; i -= 1) {
value = (value << 8n) + BigInt(bytes[i]);View on GitHub (pinned to 4deb7eca8f)
Solutions
- Ensure the enrollment/host UUID is loaded (not undefined/null) before building the request.
- Validate the string matches a UUID regex before calling.
- Strip wrappers like urn:uuid: or {...} if your source produces them.
- Log the raw value on failure to see what the server or UI actually supplied.
Example fix
// before
const bytes = enrollmentIdBytes(enrollmentId); // may be undefined
// after
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
if (!enrollmentId || !UUID_RE.test(enrollmentId)) {
throw new Error(`Bad enrollment id: ${enrollmentId}`);
}
const bytes = enrollmentIdBytes(enrollmentId); Defensive patterns
Strategy: validation
Validate before calling
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
if (!enrollmentId || !UUID_RE.test(enrollmentId)) {
throw new Error(`Invalid enrollment ID: ${enrollmentId}`);
} Type guard
function isUuid(v: unknown): v is string {
return typeof v === 'string' &&
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(v);
} Try / catch
if (!isUuid(enrollmentId)) {
showError('Enrollment ID must be a valid UUID.');
return;
}
try {
await beginEnrollment(enrollmentId);
} catch (e) { handleError(e); } Prevention
- Never build requests until async-loaded IDs have resolved (check for undefined)
- Strip urn:uuid:/{...} wrappers if your ID source emits them
- Use the canonical UUID string exactly as the server returns it
- Add a UUID regex check at the UI/boundary layer to fail early
When it happens
Trigger: Calling enrollmentIdBytes/uuidToBytes with a non-UUID string: empty value, a short ID, a UUID with braces/urn: prefix that leaves non-hex residue, or a server-returned ID field that is undefined coerced to 'undefined' (10 chars).
Common situations: Host ID or enrollment ID not yet loaded (undefined) when the pairing request is constructed; backend returning a numeric or prefixed ID where the client expects a UUID; copy/paste of a display name instead of the UUID.
Related errors
- Enrollment code must be 6 characters.
- Failed to list projects (${res.status})
- result.error
- Fallback response for "${table}" is not an object
- Fallback response missing "${table}" array
AI-assisted analysis of BloopAI/vibe-kanban@4deb7eca8f (2026-08-29).
Data as JSON: /api/errors/547bea4cf3920fb2.
Report an issue: GitHub.