BloopAI/vibe-kanban · error · Error

Failed to bulk update issues

Error message

Failed to bulk update issues

What it means

bulkUpdateIssues sends a batch of issue changes to the remote API and, if the response is not ok, throws Error(serverMessage || 'Failed to bulk update issues'). It is the issue-tracker equivalent of the project bulk-update error and surfaces server-side rejection reasons verbatim when present. Called from Actions and handleDragEnd (drag-and-drop persistence).

Source

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

  });
  if (!response.ok) {
    const error = await response.json();
    throw new Error(error.message || 'Failed to bulk update projects');
  }
}

export async function bulkUpdateIssues(
  updates: BulkUpdateIssueItem[]
): Promise<void> {
  const response = await makeRequest('/v1/issues/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 issues');
  }
}

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) {

View on GitHub (pinned to 4deb7eca8f)

Solutions

  1. Check the thrown error.message / network tab for the real server reason
  2. Refresh the issue list (re-fetch) to clear stale ids, then retry the drag/update
  3. Re-authenticate if the status was 401; the client's makeRequest retryOn401 may already have been exhausted
  4. Handle the error in handleDragEnd to roll back optimistic UI state

Example fix

// before
onDragEnd={handleDragEnd} // throws unhandled
// after
const handleDragEnd = async (e) => {
  try { await applyDrag(e); }
  catch (err) { notify.error(err.message); refetchIssues(); }
};
Defensive patterns

Strategy: try-catch

Validate before calling

const liveIds = new Set(issues.map(i => i.id));
if (updates.some(u => !liveIds.has(u.id))) { await refetchIssues(); return; }

Type guard

function isBulkUpdateItem(u: unknown): u is BulkUpdateIssueItem { return typeof u === 'object' && u !== null && typeof (u as any).id === 'string'; }

Try / catch

try {
  await bulkUpdateIssues(updates);
} catch (e) {
  rollbackOptimisticChanges(updates);
  notify.error(e instanceof Error ? e.message : 'Failed to bulk update issues');
}

Prevention

When it happens

Trigger: Non-ok HTTP response from the bulk-update-issues endpoint: a dragged issue's status/triage change rejected (deleted issue, invalid field value), auth failure, or backend error; also when the error body lacks a `message`.

Common situations: Drag-and-drop onto a column whose status value the server no longer accepts after a schema change; stale issue ids after another user deleted them; 401 from expired session mid-drag.

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/ebc405920ac96cab. Report an issue: GitHub.