BloopAI/vibe-kanban · error

Failed to bulk update ${mutation.name} (or server-provided m

Error message

Failed to bulk update ${mutation.name} (or server-provided message via parseResponseError)

What it means

When an update transaction contains multiple mutations, the library POSTs them to `${mutation.url}/bulk`; on a non-ok response it throws with the server's `message`/`error` (via parseResponseError) or the fallback 'Failed to bulk update <name>'. This rejects the whole batch, rolling back all optimistic updates in the transaction.

Source

Thrown at packages/web-core/src/shared/lib/electric/collections.ts:687

          }

          return {
            id: String(mutationItem.key),
            ...(mutationItem.changes as Record<string, unknown>),
          };
        });

        const response = await makeRequest(`${mutation.url}/bulk`, {
          method: 'POST',
          body: JSON.stringify({ updates }),
        });

        if (!response.ok) {
          const message = await parseResponseError(
            response,
            `Failed to bulk update ${mutation.name}`
          );
          throw new Error(message);
        }

        const result = (await response.json()) as { txid: number };
        txids = [result.txid];
      } else {
        const mutationItem = transaction.mutations[0];
        if (!mutationItem?.key) {
          throw new Error(`Failed to update ${mutation.name}: missing key`);
        }

        const response = await makeRequest(
          `${mutation.url}/${mutationItem.key}`,
          {
            method: 'PATCH',
            body: JSON.stringify(mutationItem.changes),
          }
        );

View on GitHub (pinned to 4deb7eca8f)

Solutions

  1. Implement/verify the POST ${mutation.url}/bulk endpoint accepting { updates: [{ id, ...changes }] } and returning { txid }.
  2. Validate every row before sending the batch; send smaller batches and surface per-row failures.
  3. Re-authenticate on 401 and retry the transaction.
  4. If bulk is unsupported, chunk client-side into single PATCH updates (one mutation per transaction).

Example fix

// before
await collection.update(id, changes); // many in one transaction -> hits /bulk
// after
for (const { id, changes } of edits) {
  await collection.utils.runTransaction? ? null : null;
}
// simpler: issue each update in its own transaction
for (const { id, changes } of edits) {
  await singleUpdateTransaction(collection, id, changes); // uses PATCH, avoids /bulk
}
Defensive patterns

Strategy: retry

Validate before calling

const invalid = updates.filter(u => u.id == null);
if (invalid.length) throw new Error('All rows need an id for bulk update');
if (updates.length > MAX_BULK) throw new Error('Batch too large; chunk it');

Type guard

function isBulkUnsupported(e: unknown): boolean {
  return e instanceof Error && e.message.startsWith('Failed to bulk update ') &&
    (e as { status?: number }).status === 404;
}

Try / catch

try {
  await bulkUpdate(collection, updates);
} catch (e) {
  if (isBulkUnsupported(e)) {
    await Promise.allSettled(updates.map(u => singleUpdate(collection, u))); // PATCH fallback
    return;
  }
  if (e instanceof Error && e.status >= 500) return retryWithBackoff(() => bulkUpdate(collection, updates));
  throw e;
}

Prevention

When it happens

Trigger: Bulk endpoint returns 404 (route `${url}/bulk` not implemented server-side), 401/403 auth failure, 422 when any single row in the batch fails validation (whole batch rejected), 409 conflicts, or 5xx.

Common situations: Backend never implemented the /bulk route while the client sends multi-row edits; one invalid row in the batch fails the entire request; bulk payload size limits exceeded on large selections; expired session during a long editing session.

Related errors


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