BloopAI/vibe-kanban · error · Error

Invitation not found (${res.status})

Error message

Invitation not found (${res.status})

What it means

getInvitation looks up a pending invitation by its token at GET {API_BASE}/v1/invitations/{token}. The function throws this Error whenever the HTTP response is not ok (res.ok false), regardless of status code. It is a plain Error with only the status number embedded in the message, so callers cannot branch on the status programmatically.

Source

Thrown at packages/remote-web/src/shared/lib/api.ts:120

  password: string,
): Promise<LocalLoginResponse> {
  const res = await fetch(`${API_BASE}/v1/auth/local/login`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ email, password }),
  });
  if (!res.ok) {
    throw new Error(`Local login failed (${res.status})`);
  }
  return res.json();
}

export async function getInvitation(
  token: string,
): Promise<InvitationLookupResponse> {
  const res = await fetch(`${API_BASE}/v1/invitations/${token}`);
  if (!res.ok) {
    throw new Error(`Invitation not found (${res.status})`);
  }
  return res.json();
}

export async function acceptInvitation(
  token: string,
  accessToken: string,
): Promise<AcceptInvitationResponse> {
  const res = await fetch(`${API_BASE}/v1/invitations/${token}/accept`, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${accessToken}`,
    },
  });
  if (!res.ok) {
    throw new Error(`Failed to accept invitation (${res.status})`);
  }

View on GitHub (pinned to 4deb7eca8f)

Solutions

  1. Ask the organization admin to resend a fresh invitation and open the new link.
  2. Verify the token in the URL matches the invitation exactly (no truncation/copy errors).
  3. Check VITE_API_BASE_URL points at the running remote server; a wrong base makes every lookup 404.
  4. Inspect res.status in the message: 404 = not found/already used, 410 = expired, 5xx = server-side issue to report.

Example fix

// before: single generic throw, status only in message
if (!res.ok) {
  throw new Error(`Invitation not found (${res.status})`);
}
// after: attach status and clearer message per case
if (!res.ok) {
  const err = new Error(
    res.status === 404
      ? "Invitation not found, already used, or revoked"
      : res.status === 410
        ? "This invitation has expired"
        : `Invitation lookup failed (${res.status})`,
  );
  (err as Error & { status: number }).status = res.status;
  throw err;
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (typeof token !== 'string' || token.trim() === '') {
  throw new Error('Invitation token is missing or empty');
}
if (!import.meta.env.VITE_API_BASE_URL && import.meta.env.PROD) {
  console.warn('VITE_API_BASE_URL is not set; requests go to same origin');
}

Type guard

function isInvitationLookup(v: unknown): v is InvitationLookupResponse {
  const r = v as InvitationLookupResponse;
  return (
    !!r && typeof r.id === 'string' && typeof r.organization_slug === 'string' &&
    typeof r.role === 'string' && typeof r.expires_at === 'string'
  );
}

Try / catch

try {
  const invitation = await getInvitation(token);
  // render invitation details
} catch (e) {
  const status = Number(/\((\d{3})\)$/.exec((e as Error).message)?.[1]);
  if (status === 404) show('Invitation not found or already used');
  else if (status === 410) show('This invitation has expired');
  else show('Could not load the invitation. Please try the link again.');
}

Prevention

When it happens

Trigger: GET /v1/invitations/{token} returns 404 (token unknown, invitation already accepted or revoked), 410 (expired invitation per expires_at), or any 4xx/5xx from the remote server. Also fires when API_BASE (VITE_API_BASE_URL) is wrong and the request hits a route that doesn't exist.

Common situations: User opens an invitation link after the invite expired; user re-opens a link after already accepting the invite; someone mangles the token in the URL; the remote-web app points at the wrong backend URL so the route 404s.

Related errors


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