{"record":{"id":"a3d9855ab03d62e9","repo":"SigNoz/signoz","slug":"internal-a3d985","errorCode":"internal","errorMessage":"cannot begin transaction","messagePattern":"cannot begin transaction","errorType":"error_code","errorClass":null,"httpStatus":500,"severity":"error","filePath":"pkg/sqlstore/bun.go","lineNumber":40,"sourceCode":"\tdb := bun.NewDB(sqldb, dialect, opts...)\n\n\tfor _, hook := range hooks {\n\t\tdb.AddQueryHook(hook)\n\t}\n\n\treturn &BunDB{db, settings}\n}\n\nfunc (db *BunDB) RunInTxCtx(ctx context.Context, opts *sql.TxOptions, cb func(ctx context.Context) error) error {\n\ttx, ok := txFromContext(ctx)\n\tif ok {\n\t\treturn cb(ctx)\n\t}\n\n\t// begin transaction\n\ttx, err := db.BeginTx(ctx, opts)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, \"cannot begin transaction\")\n\t}\n\n\tdefer func() {\n\t\tif err := tx.Rollback(); err != nil {\n\t\t\tif err != sql.ErrTxDone {\n\t\t\t\tdb.settings.Logger().ErrorContext(ctx, \"cannot rollback transaction\", errors.Attr(err))\n\t\t\t}\n\t\t}\n\t}()\n\n\tif err := cb(newContextWithTx(ctx, tx)); err != nil {\n\t\treturn err\n\t}\n\n\treturn tx.Commit()\n}\n\nfunc (db *BunDB) BunDBCtx(ctx context.Context) bun.IDB {","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/SigNoz/signoz/blob/5069bf80b08f1f00d7e014eccc09902f9871004f/pkg/sqlstore/bun.go#L22-L58","documentation":"RunInTxCtx is the generic transactional helper: when already inside a tx it just invokes the callback, otherwise it begins a new one with BeginTx. This error means a new transaction could not be started — connection acquisition failed, the context is invalid/canceled, or the DB is unavailable/read-only.","triggerScenarios":"Calling RunInTxCtx (not nested) when the pool has no available connections, ctx is canceled, the DB is restarting, or max connection limits are hit server-side.","commonSituations":"Pool saturation from leaked/long transactions, Postgres max_connections exceeded, failover in progress, canceled parent contexts (HTTP client disconnects), read-only replicas targeted by mistake.","solutions":["Inspect wrapped error: context.Canceled vs too many connections vs bad conn","Tune pool (max open conns, max idle, conn max lifetime) and check for tx leaks","Retry with backoff for transient unavailability","Point the service at a writable primary, not a read replica"],"exampleFix":"// before\nerr := sqlstore.RunInTxCtx(ctx, func(ctx context.Context) error { ... })\n\n// after\nerr := retry.Do(func() error {\n    return sqlstore.RunInTxCtx(ctx, func(ctx context.Context) error { ... })\n}, retry.Attempts(3), retry.RetryIf(isTransientConnErr))","handlingStrategy":"retry","validationCode":"if ctx.Err() != nil { return ctx.Err() }\nif err := db.PingContext(ctx); err != nil { return err }","typeGuard":"func isBeginTxFailure(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"cannot begin transaction\")\n}","tryCatchPattern":"err := sqlstore.RunInTxCtx(ctx, cb)\nif isBeginTxFailure(err) && isTransientDBErr(errors.Unwrap(err)) {\n    time.Sleep(250*time.Millisecond)\n    err = sqlstore.RunInTxCtx(ctx, cb)\n}","preventionTips":["Tune pool max connections/lifetime; watch for tx leaks","Write callbacks idempotent so retries are safe","Target writable primaries, not read replicas"],"tags":["database","transaction","connection-pool","bun-orm"],"backgroundTag":"db-transaction-begin-failed","analyzedSha":"5069bf80b08f1f00d7e014eccc09902f9871004f","analyzedAt":"2026-08-28T06:22:12.824Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}