{"record":{"id":"1d335949ca31b046","repo":"gastownhall/beads","slug":"get-dependencies-fetch-issues-w","errorCode":null,"errorMessage":"get dependencies: fetch issues: %w","messagePattern":"get dependencies: fetch issues: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/issueops/dependencies.go","lineNumber":1137,"sourceCode":"\t\t}\n\t\t_ = rows.Close()\n\t\tif err := rows.Err(); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"get dependencies: rows from %s: %w\", depTable, err)\n\t\t}\n\t}\n\n\tif len(deps) == 0 {\n\t\treturn nil, nil\n\t}\n\n\t// Fetch all dependency target issues.\n\tids := make([]string, len(deps))\n\tfor i, d := range deps {\n\t\tids[i] = d.depID\n\t}\n\tissues, err := GetIssuesByIDsInTx(ctx, tx, ids, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"get dependencies: fetch issues: %w\", err)\n\t}\n\tissueMap := make(map[string]*types.Issue, len(issues))\n\tfor _, iss := range issues {\n\t\tissueMap[iss.ID] = iss\n\t}\n\n\tvar results []*types.IssueWithDependencyMetadata\n\tfor _, d := range deps {\n\t\tissue, ok := issueMap[d.depID]\n\t\tif !ok {\n\t\t\tcontinue\n\t\t}\n\t\tresults = append(results, &types.IssueWithDependencyMetadata{\n\t\t\tIssue:          *issue,\n\t\t\tDependencyType: types.DependencyType(d.depType),\n\t\t})\n\t}\n\treturn results, nil","sourceCodeStart":1119,"sourceCodeEnd":1155,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/issueops/dependencies.go#L1119-L1155","documentation":"GetDependenciesWithMetadataInTx wraps any error from GetIssuesByIDsInTx when hydrating the issues that the dependency rows point to. The dependency edges themselves were read fine, but fetching the target issue records by their IDs failed. The original error (scan failure, query error, etc.) is preserved via %w.","triggerScenarios":"GetDependenciesWithMetadataInTx found dependency rows, then GetIssuesByIDsInTx failed on the batched SELECT over the collected depends-on IDs — e.g. query error, scan error, or rows error inside the ID-based fetch.","commonSituations":"Corrupt or mismatched schema between the dependency table and issues/wisp issues tables; oversized IN clause from a huge dependency list; transient DB failure between the two queries; strict type mismatch when scanning issue rows.","solutions":["Inspect the wrapped GetIssuesByIDsInTx error (unwrap the %w chain) to find the real failure.","Check schema consistency: every ID in dependencies/wisp_dependencies should exist in issues or wisp_issues with compatible column types.","If the dependency list is very large, verify the IN-clause handling/parameter limits of your driver.","Retry on a fresh transaction if the wrapped error is transient."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Pre-check that dependency targets resolve before hydration-heavy calls\nids, err := collectDependencyIDs(ctx, tx, issueID)\nif err != nil { return err }\nif len(ids) > 1000 { return fmt.Errorf(\"dependency fan-out too large: %d\", len(ids)) }","typeGuard":"func isFetchIssuesErr(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"fetch issues\")\n}","tryCatchPattern":"deps, err := GetDependenciesWithMetadataInTx(ctx, tx, issueID)\nif err != nil {\n    if strings.Contains(err.Error(), \"fetch issues\") {\n        log.Printf(\"hydration failed: %v\", errors.Unwrap(err))\n    }\n    return err\n}","preventionTips":["Keep dependency tables and issue tables in schema sync via migrations.","Watch for orphan dependency rows referencing missing issues.","Unwrap nested errors to see the real GetIssuesByIDsInTx cause before guessing.","Cap traversal size to avoid oversized IN clauses."],"tags":["database","sql","go","hydration"],"backgroundTag":"sql-query-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}