BloopAI/vibe-kanban · error · Error

Failed to bulk update project statuses

Error message

Failed to bulk update project statuses

What it means

bulkUpdateProjectStatuses persists a batch of project status transitions via the remote API. A non-ok response causes it to throw Error(serverMessage || 'Failed to bulk update project statuses'). Invoked by persistStatusChanges, so failures there propagate into the status persistence flow.

Source

Thrown at packages/web-core/src/shared/lib/remoteApi.ts:156

}

export interface BulkUpdateProjectStatusItem {
  id: string;
  changes: Partial<UpdateProjectStatusRequest>;
}

export async function bulkUpdateProjectStatuses(
  updates: BulkUpdateProjectStatusItem[]
): Promise<void> {
  const response = await makeRequest('/v1/project_statuses/bulk', {
    method: 'POST',
    body: JSON.stringify({
      updates: updates.map((u) => ({ id: u.id, ...u.changes })),
    }),
  });
  if (!response.ok) {
    const error = await response.json();
    throw new Error(error.message || 'Failed to bulk update project statuses');
  }
}

// ---------------------------------------------------------------------------
// Relay host API functions (served by remote backend)
// ---------------------------------------------------------------------------

export async function listRelayHosts(): Promise<RelayHost[]> {
  const response = await makeRequest('/v1/hosts', { method: 'GET' });
  if (!response.ok) {
    throw await parseErrorResponse(response, 'Failed to list relay hosts');
  }

  const body = (await response.json()) as ListRelayHostsResponse;
  return body.hosts;
}

// ---------------------------------------------------------------------------

View on GitHub (pinned to 4deb7eca8f)

Solutions

  1. Inspect the thrown error.message and response status for the exact rejection
  2. Verify the status values match the current API enum (regenerate shared/remote-types if the API changed)
  3. Re-fetch projects and retry after a 401/refresh of auth
  4. Make persistStatusChanges catch and surface the error instead of letting it bubble silently
Defensive patterns

Strategy: try-catch

Validate before calling

const validStatuses = new Set(['planning','in_progress','review','done']);
if (updates.some(u => !validStatuses.has(Object.values(u.changes)[0] as string))) throw new Error('invalid status value');

Type guard

function isStatusUpdate(u: BulkUpdateProjectStatusItem): boolean { return typeof u.id === 'string' && Object.keys(u.changes).length > 0; }

Try / catch

try {
  await bulkUpdateProjectStatuses(updates);
} catch (e) {
  console.error('status persist failed:', e);
  notify.error(e instanceof Error ? e.message : 'Failed to persist statuses');
}

Prevention

When it happens

Trigger: Non-ok HTTP from the bulk-update-project-statuses endpoint: invalid status transition, unknown project id, expired auth, server error, or an error body without `message`.

Common situations: Status enum changed between frontend/backend versions (client sends a status the server rejects); concurrent edits where the project was deleted; offline/self-hosted gateway returning non-JSON errors.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


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