temporalio/temporal · error
%v rows were affected instead of 1
Error message
%v rows were affected instead of 1
What it means
After an UpdateTaskQueue SQL statement executes, the code checks result.RowsAffected() and requires exactly 1 row to be modified. If the statement affected 0 or multiple rows, it returns this error, indicating the assumed single-row update invariant was violated (usually the task queue row did not exist or a range/condition matched unexpectedly).
Source
Thrown at common/persistence/sql/task_queues.go:122
); err != nil {
return err
}
result, err := tx.UpdateTaskQueues(ctx, &sqlplugin.TaskQueuesRow{
RangeHash: tqHash,
TaskQueueID: tqId,
RangeID: request.RangeID,
Data: request.TaskQueueInfo.Data,
DataEncoding: request.TaskQueueInfo.EncodingType.String(),
}, m.version)
if err != nil {
return err
}
rowsAffected, err := result.RowsAffected()
if err != nil {
return err
}
if rowsAffected != 1 {
return fmt.Errorf("%v rows were affected instead of 1", rowsAffected)
}
resp = &persistence.UpdateTaskQueueResponse{}
return nil
})
return resp, err
}
func (m *taskQueueStore) ListTaskQueue(
ctx context.Context,
request *persistence.ListTaskQueueRequest,
) (*persistence.InternalListTaskQueueResponse, error) {
pageToken := taskQueuePageToken{MinTaskQueueId: minTaskQueueId}
if request.PageToken != nil {
if err := gobDeserialize(request.PageToken, &pageToken); err != nil {
return nil, serviceerror.NewInternalf("error deserializing page token: %v", err)
}
}
var err errorView on GitHub (pinned to bde624efd1)
Solutions
- Verify the task queue exists (ListTaskQueue/DescribeTaskQueue) before updating and that namespaceID/name are correct.
- Check for concurrent operations racing on the same task queue row; retry the operation or re-fetch rangeID after the conflict.
- Confirm rangeID/range conditions passed to UpdateTaskQueue match current shard state; reload shard state if stale.
- Inspect the DB row directly to see whether the expected row exists and whether the UPDATE WHERE clause could match multiple rows.
Example fix
// before
resp, err := p.UpdateTaskQueue(ctx, req) // rowsAffected == 0
// after
existing, err := p.GetTaskQueue(ctx, getReq)
if err != nil { return err }
resp, err := p.UpdateTaskQueue(ctx, req) // with valid rangeID from existing Defensive patterns
Strategy: retry
Validate before calling
// pre-check the queue exists and rangeID is current
_, err := persistenceStore.GetTaskQueue(ctx, &persistence.GetTaskQueueRequest{NamespaceID: nsID, Name: tqName, TaskType: taskType}) Try / catch
resp, err := store.UpdateTaskQueue(ctx, req)
if err != nil && strings.Contains(err.Error(), "rows were affected") {
// re-fetch rangeID / shard state and retry once
return retryWithFreshRangeID(ctx, req)
}
return err Prevention
- Always pass a freshly loaded rangeID; never cache range state across retries.
- Expect concurrency: task queue updates are racy, wrap in retry with backoff.
- Confirm the queue wasn't deleted/recreated between get and update.
When it happens
Trigger: Calling persistence.UpdateTaskQueue when the task_queues row for the given (namespaceID, name, rangeID/kind) does not exist, or when a conditional UPDATE whose WHERE clause matches more than one row is executed.
Common situations: Task queue deleted concurrently by a reaper while being updated, stale rangeID causing the optimistic-condition UPDATE to match nothing, DB replication/divergence, running against a schema where the unique key assumptions don't hold.
Related errors
- page size to read history tasks must be positive
- history task from queue has nil blob
- enqueue task request task is nil
- queue already exists
- shard ID must be greater than 0
AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01).
Data as JSON: /api/errors/455098f24cdb3016.
Report an issue: GitHub.