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

  1. Ensure the enrollment/host UUID is loaded (not undefined/null) before building the request.
  2. Validate the string matches a UUID regex before calling.
  3. Strip wrappers like urn:uuid: or {...} if your source produces them.
  4. 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

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


AI-assisted analysis of BloopAI/vibe-kanban@4deb7eca8f (2026-08-29). Data as JSON: /api/errors/547bea4cf3920fb2. Report an issue: GitHub.