{"record":{"id":"4943bac65e147bf6","repo":"gastownhall/beads","slug":"delete-staging-branch-w","errorCode":null,"errorMessage":"delete staging branch: %w","messagePattern":"delete staging branch: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/storage/dolt/federation.go","lineNumber":579,"sourceCode":"// fresh, uncanceled, bounded connection. Errors are joined; a non-nil result is\n// wrapped by the caller with the \"federation filter: cleanup\" context.\nfunc cleanupFilteredStaging(ctx context.Context, db *sql.DB, conn *sql.Conn, sourceBranch, stagingBranch string) error {\n\tcleanupCtx, cancel := context.WithTimeout(context.WithoutCancel(ctx), federationStagingCleanupTimeout)\n\tdefer cancel()\n\tvar cleanupErr error\n\tif err := conn.Close(); err != nil {\n\t\tcleanupErr = errors.Join(cleanupErr, fmt.Errorf(\"discard operation connection: %w\", err))\n\t}\n\tcleanupConn, err := db.Conn(cleanupCtx)\n\tif err != nil {\n\t\tcleanupErr = errors.Join(cleanupErr, fmt.Errorf(\"acquire cleanup connection: %w\", err))\n\t} else {\n\t\tdefer cleanupConn.Close()\n\t\tif err := schema.DrainCall(cleanupCtx, cleanupConn, \"CALL DOLT_CHECKOUT(?)\", sourceBranch); err != nil {\n\t\t\tcleanupErr = errors.Join(cleanupErr, fmt.Errorf(\"restore branch %s: %w\", sourceBranch, err))\n\t\t}\n\t\tif err := deleteFederationStagingBranch(cleanupCtx, cleanupConn, stagingBranch); err != nil {\n\t\t\tcleanupErr = errors.Join(cleanupErr, fmt.Errorf(\"delete staging branch: %w\", err))\n\t\t}\n\t}\n\treturn cleanupErr\n}\n\nfunc deleteFederationStagingBranch(ctx context.Context, conn *sql.Conn, stagingBranch string) error {\n\terr := schema.DrainCall(ctx, conn, \"CALL DOLT_BRANCH('-Df', ?)\", stagingBranch)\n\tvar mysqlErr *mysql.MySQLError\n\t// Dolt reports a missing branch as generic error 1105; match the message as\n\t// a case-insensitive substring (as RemoteRefUnavailableErr does) because\n\t// Dolt may append the branch/ref name to this class of error.\n\tif errors.As(err, &mysqlErr) && mysqlErr.Number == 1105 &&\n\t\tstrings.Contains(strings.ToLower(mysqlErr.Message), \"branch not found\") {\n\t\treturn nil\n\t}\n\treturn err\n}\n","sourceCodeStart":561,"sourceCodeEnd":597,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/dolt/federation.go#L561-L597","documentation":"Wraps an error from deleteFederationStagingBranch, which drops a temporary staging branch created during filtered federation push/pull. Cleanup runs in a deferred path after a failed or completed operation, and the error is accumulated into cleanupErr via errors.Join so earlier failures are preserved. It means the Dolt CALL DOLT_BRANCH('-D', ...) (or equivalent) on the cleanup connection failed, potentially leaving a stale staging branch behind.","triggerScenarios":"cleanupFilteredStaging's deferred/else path calls deleteFederationStagingBranch and the underlying SQL delete of the staging branch fails (connection lost, branch checked out in another session, permissions, or the branch name doesn't exist).","commonSituations":"Network drop or server restart mid-operation; another Dolt session is checked out on the staging branch so DOLT_BRANCH -D refuses; database was recreated so the branch no longer exists; partially created staging branch from an earlier crashed run.","solutions":["Re-run the operation; check for and manually drop leftover staging branches with CALL DOLT_BRANCH('-D', '<staging-branch>')","Inspect the wrapped inner error (errors.Join output) to find the root Dolt cause before retrying","Ensure no other connection/session holds the staging branch checked out during cleanup","Verify the cleanup connection (cleanupConn) is still alive and cleanupCtx has not been canceled"],"exampleFix":"// before\nif err := deleteFederationStagingBranch(cleanupCtx, cleanupConn, stagingBranch); err != nil {\n\tcleanupErr = errors.Join(cleanupErr, fmt.Errorf(\"delete staging branch: %w\", err))\n}\n// after\nif err := deleteFederationStagingBranch(cleanupCtx, cleanupConn, stagingBranch); err != nil {\n\t// Idempotent retry: a missing branch on cleanup is harmless\n\tvar doltErr *mysql.MySQLError\n\tif !errors.As(err, &doltErr) || doltErr.Number != errno.ErrNoSuchTable {\n\t\tcleanupErr = errors.Join(cleanupErr, fmt.Errorf(\"delete staging branch: %w\", err))\n\t}\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"result, err := stageFilteredBranch(ctx, ...)\nif err != nil {\n\t// cleanup errors are joined; check for staging branch leftovers\n\tvar joined interface{ Unwrap() []error }\n\tif errors.As(err, &joined) { /* log each joined cleanup error */ }\n\t// then manually: CALL DOLT_BRANCH('-D', stagingBranch) to reclaim\n}","preventionTips":["Avoid multiple sessions on the same staging branch","Set generous cleanupCtx deadlines","Periodically sweep orphaned *staging* branches"],"tags":["dolt","branch-cleanup","federation","storage"],"backgroundTag":"dolt-branch-cleanup-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}