temporalio/temporal · error · Unavailable
rowsAffected returned error when initializing DLQ metadata
Error message
rowsAffected returned error when initializing DLQ metadata %v: %v
What it means
Thrown by initializeDLQMetadata in the SQL queue store after an INSERT of DLQ metadata succeeds, but result.RowsAffected() returns a driver error. Temporal expects exactly one metadata row to be created during DLQ initialization; if the driver cannot report affected-row counts, initialization cannot be verified and fails. This usually signals a database driver that does not support RowsAffected for this statement.
Source
Thrown at common/persistence/sql/queue.go:368
) error {
_, err := q.DB.SelectFromQueueMetadata(ctx, sqlplugin.QueueMetadataFilter{
QueueType: q.getDLQTypeFromQueueType(),
})
switch err {
case nil:
return nil
case sql.ErrNoRows:
result, err := q.DB.InsertIntoQueueMetadata(ctx, &sqlplugin.QueueMetadataRow{
QueueType: q.getDLQTypeFromQueueType(),
Data: blob.Data,
DataEncoding: blob.EncodingType.String(),
})
if err != nil {
return serviceerror.NewUnavailablef("initializeDLQMetadata operation failed. Error %v", err)
}
rowsAffected, err := result.RowsAffected()
if err != nil {
return fmt.Errorf("rowsAffected returned error when initializing DLQ metadata %v: %v", q.queueType, err)
}
if rowsAffected != 1 {
return fmt.Errorf("rowsAffected returned %v DLQ metadata instead of one", rowsAffected)
}
return nil
default:
return err
}
}
func newQueueRow(
queueType persistence.QueueType,
messageID int64,
blob *commonpb.DataBlob,
) sqlplugin.QueueMessageRow {
return sqlplugin.QueueMessageRow{
QueueType: queueType,View on GitHub (pinned to bde624efd1)
Solutions
- Check that the SQL driver in use (go-sql-driver/mysql, lib/pq, sqlite) supports RowsAffected on INSERT — upgrade the driver to the latest version.
- Inspect the wrapped driver error (%v at the end of the message) for the root cause (connection reset, unsupported method).
- Verify the database backend is one of the officially supported ones (MySQL, PostgreSQL, SQLite).
- Retry queue Init; if transient connection issues caused it, the next attempt may find the row already inserted and return nil early.
Defensive patterns
Strategy: retry
Try / catch
if err := q.Init(); err != nil {
if strings.Contains(err.Error(), "rowsAffected returned error") {
// transient driver issue; retry with backoff
}
return err
} Prevention
- Use only supported SQL drivers (MySQL, Postgres, SQLite) with current versions.
- Monitor DB connection health to catch drivers failing mid-statement.
- Read the trailing wrapped driver error to pinpoint root cause before retrying.
When it happens
Trigger: Init() -> initializeDLQMetadata on a queue with no existing metadata row: SELECT returns sql.ErrNoRows, INSERT succeeds, then result.RowsAffected() itself returns an error from the SQL driver.
Common situations: Using a database or driver whose RowsAffected implementation is unsupported for INSERT statements; driver/connection issues right after the insert; non-MySQL/Postgres backends with partial driver support.
Related errors
- rowsAffected returned error for shardID %v: %v
- queue already exists
- rowsAffected returned %v shards instead of one
- error initializing cluster metadata manager: %w
- error while fetching cluster metadata: %w
AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01).
Data as JSON: /api/errors/af6b0e810b0bfdfc.
Report an issue: GitHub.