{"record":{"id":"80bef8d5cd9bf618","repo":"gastownhall/beads","slug":"remaining-blocker-rows-from-s-w","errorCode":null,"errorMessage":"remaining blocker rows from %s: %w","messagePattern":"remaining blocker rows from (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/issueops/dependency_queries.go","lineNumber":863,"sourceCode":"\t\t\t`, DepTargetExpr, depTable, placeholders, DepTargetExpr), append(batchArgs, closedIssueID)...)\n\t\t\tif err != nil {\n\t\t\t\tif optionalBlockedTable(depTable) && isTableNotExistError(err) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\treturn nil, fmt.Errorf(\"check remaining blockers from %s: %w\", depTable, err)\n\t\t\t}\n\t\t\tfor depRows.Next() {\n\t\t\t\tvar candidateID, blockerID string\n\t\t\t\tif err := depRows.Scan(&candidateID, &blockerID); err != nil {\n\t\t\t\t\t_ = depRows.Close()\n\t\t\t\t\treturn nil, fmt.Errorf(\"scan remaining blocker: %w\", err)\n\t\t\t\t}\n\t\t\t\tremainingByCandidate[candidateID] = append(remainingByCandidate[candidateID], blockerID)\n\t\t\t\tremainingBlockerSet[blockerID] = struct{}{}\n\t\t\t}\n\t\t\t_ = depRows.Close()\n\t\t\tif err := depRows.Err(); err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"remaining blocker rows from %s: %w\", depTable, err)\n\t\t\t}\n\t\t}\n\n\t\tremainingBlockerIDs := make([]string, 0, len(remainingBlockerSet))\n\t\tfor blockerID := range remainingBlockerSet {\n\t\t\tremainingBlockerIDs = append(remainingBlockerIDs, blockerID)\n\t\t}\n\t\tsort.Strings(remainingBlockerIDs)\n\t\tstatusByID, err := loadStatusByIDInTx(ctx, tx, remainingBlockerIDs)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"check remaining blocker status: %w\", err)\n\t\t}\n\t\tfor candidateID, blockerIDs := range remainingByCandidate {\n\t\t\tfor _, blockerID := range blockerIDs {\n\t\t\t\tstatus, ok := statusByID[blockerID]\n\t\t\t\tif ok && status != types.StatusClosed && status != types.StatusPinned {\n\t\t\t\t\tstillBlocked[candidateID] = true\n\t\t\t\t\tbreak","sourceCodeStart":845,"sourceCodeEnd":881,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/issueops/dependency_queries.go#L845-L881","documentation":"Wraps an error from depRows.Err() after iterating the remaining-blocker result set in GetNewlyUnblockedByCloseInTx. This catches errors that surfaced asynchronously during row streaming (connection drop, driver I/O failure) rather than at query or scan time. It fails the unblock computation to avoid returning a partially computed result.","triggerScenarios":"The underlying connection or driver encounters an I/O or protocol error while streaming rows from a dependency table, detected only after the loop finishes via rows.Err().","commonSituations":"Embedded DB file locked or disconnected mid-query; network interruption to a remote Dolt SQL server; context cancellation during long iteration.","solutions":["Check the wrapped error for connection/context details","If it is context cancellation, raise the timeout or avoid cancelling mid-transaction","For network drivers, verify server connectivity and retry the transaction","For embedded storage, check for file locks/corruption and repair"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := tx.CloseIssue(ctx, id); err != nil {\n\tif errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {\n\t\t// retry with a longer-lived context\n\t}\n\treturn err\n}","preventionTips":["Use generous timeouts for close/unblock operations","Avoid suspending machines or killing processes mid-transaction","For remote Dolt servers, monitor connection stability"],"tags":["go","sql","row-iteration","storage"],"backgroundTag":"row-iteration-error","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}