ABORTED
gRPCERRORNotableConcurrencyHIGH confidence

The operation was aborted

What this means

Indicates the operation was aborted, typically due to a concurrency issue like a transaction abort or a check-and-set failure. This suggests a retry might succeed.

Why it happens
  1. 1A read-modify-write operation failed because the data was modified by another transaction after it was read.
  2. 2A concurrency control mechanism, like optimistic locking, detected a conflict.
  3. 3The server aborted the operation to resolve a deadlock.
How to reproduce

Two clients try to update the same database record at the same time, causing a transaction to be aborted.

trigger — this will error
trigger — this will error
// This usually happens in a read-modify-write sequence.
// 1. Client A reads resource version 5.
// 2. Client B reads resource version 5, modifies it, and writes version 6.
// 3. Client A modifies its copy and tries to write version 6, but the server rejects it.
try {
  await client.updateUser(updateRequestWithOldVersion);
} catch (e) {
  // e.code will be ABORTED
}

expected output

StatusCode.ABORTED: The operation was aborted

Fix 1

Retry the Full Read-Modify-Write Transaction

WHEN When an optimistic concurrency conflict occurs.

Retry the Full Read-Modify-Write Transaction
// Retry the entire transaction
for (let i = 0; i < 3; i++) {
  try {
    const current = await client.getResource(id);
    const updated = modify(current);
    await client.updateResource(updated);
    return; // Success
  } catch (e) {
    if (e.code !== grpc.status.ABORTED) throw e;
  }
}

Why this works

By re-reading the latest version of the data before attempting the write again, the client can resolve the conflict.

Fix 2

Use Pessimistic Locking

WHEN When conflicts are very frequent and retries are costly.

Use Pessimistic Locking
// This requires server-side support for locking.
await client.lockResource({ id });
try {
  const resource = await client.getResource({ id });
  await client.updateResource(modify(resource));
} finally {
  await client.unlockResource({ id });
}

Why this works

Pessimistic locking prevents other clients from accessing a resource while it is being modified, avoiding conflicts altogether.

What not to do

✕ Only retry the write portion of the operation

The client's modification was based on stale data. It must re-read the latest data before trying to apply its changes again.

Sources

Content generated with AI assistance and reviewed for accuracy. Found an error? hello@errcodes.dev

← All gRPC errors