{"record":{"id":"cde0b0e2d4bc2019","repo":"gastownhall/beads","slug":"iterate-neighbors-from-s-w","errorCode":null,"errorMessage":"iterate neighbors from %s: %w","messagePattern":"iterate neighbors from (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/issueops/delete_role.go","lineNumber":289,"sourceCode":"\t\t\t\t}\n\t\t\t\treturn nil, fmt.Errorf(\"query neighbors from %s: %w\", depTable, err)\n\t\t\t}\n\t\t\tfor rows.Next() {\n\t\t\t\tvar source, target string\n\t\t\t\tif err := rows.Scan(&source, &target); err != nil {\n\t\t\t\t\t_ = rows.Close()\n\t\t\t\t\treturn nil, fmt.Errorf(\"scan neighbor: %w\", err)\n\t\t\t\t}\n\t\t\t\tfor _, candidate := range [2]string{source, target} {\n\t\t\t\t\tif candidate == \"\" || deleting[candidate] {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tneighborIDs[candidate] = true\n\t\t\t\t}\n\t\t\t}\n\t\t\t_ = rows.Close()\n\t\t\tif err := rows.Err(); err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"iterate neighbors from %s: %w\", depTable, err)\n\t\t\t}\n\t\t}\n\t}\n\tif len(neighborIDs) == 0 {\n\t\treturn nil, nil\n\t}\n\n\t// Sorted so the rewrite touches rows in a stable order, which is what\n\t// makes a partially-applied failure reproducible.\n\thydrate := workapi.SortedDeleteIDs(neighborIDs)\n\t// An `external:` target and a target belonging to another repository name\n\t// no row here; GetIssuesByIDsInTx simply does not return them.\n\tissues, err := GetIssuesByIDsInTx(ctx, tx, hydrate, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"hydrate neighbors: %w\", err)\n\t}\n\treturn issues, nil\n}","sourceCodeStart":271,"sourceCodeEnd":307,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/issueops/delete_role.go#L271-L307","documentation":"After the neighbor-iteration loop, rows.Err() reported a deferred failure from the result stream — the classic pattern for a connection drop or cancellation that only surfaces once rows are exhausted. The wrapper names the dependency table whose iteration failed. The whole delete (including the pending deletion in this transaction) aborts and rolls back.","triggerScenarios":"deleteNeighborsInTx closes rows after scanning neighbors from dependencies/wisp_dependencies and rows.Err() is non-nil — network interruption, server abort, or context cancellation mid-stream.","commonSituations":"Remote Dolt/MySQL connection reset during a large neighborhood read; context deadline exceeded on a big cascade; server-side query kill (max_execution_time).","solutions":["Retry the delete in a fresh transaction; it is safe — nothing committed","Increase the context timeout for large cascades","Check server logs for aborted queries and network stability","Split very large deletes into smaller batches to shrink each result stream"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"if err := ctx.Err(); err != nil { return err }","typeGuard":null,"tryCatchPattern":"err := store.Delete(ctx, req)\nif err != nil && strings.Contains(err.Error(), \"iterate neighbors from\") {\n    // deferred rows.Err() mid-stream; whole tx rolled back, retry safely\n    return retryDelete(req, longerTimeout)\n}","preventionTips":["Give wide-neighborhood deletes generous context budgets","Monitor for server-side query kills (execution time limits)","Batch very large deletes to shrink each result stream","Keep database and client on the same network segment where possible"],"tags":["database","network","iteration","wrapper-error"],"backgroundTag":"db-connection-dropped","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}