{"record":{"id":"dbb3fb3a8af96c32","repo":"gastownhall/beads","slug":"journal-query-dependency-removals-from-s-w","errorCode":null,"errorMessage":"journal: query dependency removals from %s: %w","messagePattern":"journal: query dependency removals from (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/issueops/journal_dependencies.go","lineNumber":93,"sourceCode":"\tbyKey := make(map[string]journalDependencyEdge)\n\tfor start := 0; start < len(ids); start += deleteBatchSize {\n\t\tend := start + deleteBatchSize\n\t\tif end > len(ids) {\n\t\t\tend = len(ids)\n\t\t}\n\t\tinClause, args := buildSQLInClause(ids[start:end])\n\t\tqueryArgs := append(append([]any{}, args...), args...)\n\t\t//nolint:gosec // table is validated above and inClause contains only placeholders.\n\t\trows, err := tx.QueryContext(ctx, fmt.Sprintf(`\n\t\t\tSELECT issue_id, %s AS target, type, metadata\n\t\t\tFROM %s\n\t\t\tWHERE issue_id IN (%s) OR %s IN (%s)\n\t\t`, DepTargetExpr, table, inClause, DepTargetExpr, inClause), queryArgs...)\n\t\tif err != nil {\n\t\t\tif optionalBlockedTable(table) && isTableNotExistError(err) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn nil, fmt.Errorf(\"journal: query dependency removals from %s: %w\", table, err)\n\t\t}\n\t\tfor rows.Next() {\n\t\t\tvar edge journalDependencyEdge\n\t\t\tif err := rows.Scan(&edge.source, &edge.target, &edge.kind, &edge.metadata); err != nil {\n\t\t\t\t_ = rows.Close()\n\t\t\t\treturn nil, fmt.Errorf(\"journal: scan dependency removal from %s: %w\", table, err)\n\t\t\t}\n\t\t\tbyKey[dependencyEdgeKey(edge)] = edge\n\t\t}\n\t\tif err := rows.Err(); err != nil {\n\t\t\t_ = rows.Close()\n\t\t\treturn nil, fmt.Errorf(\"journal: iterate dependency removals from %s: %w\", table, err)\n\t\t}\n\t\tif err := rows.Close(); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"journal: close dependency removals from %s: %w\", table, err)\n\t\t}\n\t}\n\treturn sortedDependencyEdges(byKey), nil","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/issueops/journal_dependencies.go#L75-L111","documentation":"dependencyEdgesInTableForIssueIDsInTx queries one dependency table (per `table`) for edges touching the given issue IDs, to record removal events. This error wraps a QueryContext failure for that table. Note: for optional tables whose absence is expected (optionalBlockedTable), a table-not-exist error is skipped silently — this error only surfaces for required tables or unexpected errors.","triggerScenarios":"RecordDependencyRemovalsForTableInTx / dependencyEdgesForIssueIDsInTx failing on a table: the dependency table is missing and is NOT in the optional set (genuine migration gap), IN-clause too large or malformed, connection loss, or permission denial.","commonSituations":"Partial migration leaving a required dependency table absent; extremely large issue-ID batches blowing query size limits; locking during schema changes.","solutions":["Run migrations to create the missing dependency table (a missing required table is not auto-skipped).","Chunk the issue-ID list so the IN (...) clause and placeholder count stay within driver limits.","Retry on transient lock/connection errors.","Confirm which `table` name appears in the message and check its existence/permissions directly."],"exampleFix":"// before\nstore.RecordDependencyRemovals(ctx, allIDs) // 50k IDs in one IN clause\n// after\nfor chunk := range slices.Chunk(allIDs, 1000) {\n  if err := store.RecordDependencyRemovals(ctx, chunk); err != nil { return err }\n}","handlingStrategy":"validation","validationCode":"for _, t := range depTables {\n    var exists int\n    if err := db.QueryRow(\"SELECT COUNT(*) FROM information_schema.tables WHERE table_name = ?\", t).Scan(&exists); err != nil {\n        return err\n    }\n    if exists == 0 && !isOptionalTable(t) { return fmt.Errorf(\"required table %s missing; run migrations\", t) }\n}","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"journal: query dependency removals from\") {\n    if strings.Contains(err.Error(), \"doesn't exist\") { return runMigrationsAndRetry() }\n    if isTransient(err) { return retryWithSmallerBatch(ids) }\n    return err\n}","preventionTips":["Run migrations before dependency-removal recording.","Chunk issue-ID batches to keep IN-clauses within driver limits.","Verify all dependency tables exist after restores.","Retry transient SQL errors around schema-change windows."],"tags":["storage","database","journal","dependencies"],"backgroundTag":"dependency-table-query-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}