{"record":{"id":"2363fca812486ea5","repo":"gastownhall/beads","slug":"get-dependencies-from-s-w","errorCode":null,"errorMessage":"get dependencies from %s: %w","messagePattern":"get dependencies from (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/issueops/dependencies.go","lineNumber":1110,"sourceCode":"}\n\n// GetDependenciesWithMetadataInTx returns issues that the given issueID depends on,\n// along with the dependency type. Works within an existing transaction.\n// Queries both dependency tables to handle cross-table dependencies.\n//\n//nolint:gosec // G201: table names come from hardcoded constants\nfunc GetDependenciesWithMetadataInTx(ctx context.Context, tx DBTX, issueID string) ([]*types.IssueWithDependencyMetadata, error) {\n\ttype depMeta struct {\n\t\tdepID, depType string\n\t}\n\n\t// Query both dependency tables to find all dependencies.\n\tvar deps []depMeta\n\tfor _, depTable := range []string{\"dependencies\", \"wisp_dependencies\"} {\n\t\trows, err := tx.QueryContext(ctx, fmt.Sprintf(\n\t\t\t`SELECT %s AS depends_on_id, type FROM %s WHERE issue_id = ?`, DepTargetExpr, depTable), issueID)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"get dependencies from %s: %w\", depTable, err)\n\t\t}\n\t\tfor rows.Next() {\n\t\t\tvar d depMeta\n\t\t\tif scanErr := rows.Scan(&d.depID, &d.depType); scanErr != nil {\n\t\t\t\t_ = rows.Close()\n\t\t\t\treturn nil, fmt.Errorf(\"get dependencies: scan: %w\", scanErr)\n\t\t\t}\n\t\t\tdeps = append(deps, d)\n\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}","sourceCodeStart":1092,"sourceCodeEnd":1128,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/issueops/dependencies.go#L1092-L1128","documentation":"Wraps a QueryContext error while enumerating an issue's dependencies from one of the two dependency tables in GetDependenciesWithMetadataInTx. The table name is embedded so you know whether 'dependencies' or 'wisp_dependencies' failed.","triggerScenarios":"The `SELECT ... AS depends_on_id, type FROM <depTable> WHERE issue_id = ?` query fails for either table — missing table, driver error, or connection failure while building a dependency tree (via buildDependencyTreeInTx or ExecuteRelated).","commonSituations":"Partial migration leaving wisp_dependencies absent; transaction aborted by an earlier error; connection drop mid-tree-build when walking deep dependency graphs.","solutions":["Confirm both dependencies tables exist (run migrations)","Address the wrapped driver error — often transient; retry","Check for earlier statements in the transaction that aborted it","If DepTargetExpr SQL fragment was customized, validate it against the driver"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Preflight: verify both dependency tables exist before tree building:\nfor _, tbl := range []string{\"dependencies\", \"wisp_dependencies\"} {\n    var n int\n    err := db.QueryRowContext(ctx, `SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name = ?`, tbl).Scan(&n)\n    if err != nil || n == 0 { return fmt.Errorf(\"missing dependency table %s; run migrations\", tbl) }\n}","typeGuard":null,"tryCatchPattern":"deps, err := ops.GetDependenciesWithMetadataInTx(ctx, tx, issueID)\nif err != nil && strings.Contains(err.Error(), \"get dependencies from\") {\n    if isMissingTable(err) { return runMigrationsThenRetry(ctx) }\n    if isTransientDBError(err) { deps, err = ops.GetDependenciesWithMetadataInTx(ctx, tx, issueID) }\n    if err != nil { return err }\n}","preventionTips":["Run complete migrations so both dependency tables exist","Avoid deep/unbounded tree walks that hold transactions open","Validate custom SQL fragments (DepTargetExpr) against your driver","Check for earlier transaction errors that may have aborted the tx"],"tags":["database","sql","dependencies","go"],"backgroundTag":"sql-query-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}