{"record":{"id":"343c6139180b5c67","repo":"gastownhall/beads","slug":"query-dependency-conflicts-w","errorCode":null,"errorMessage":"query dependency conflicts: %w","messagePattern":"query dependency conflicts: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/versioncontrolops/mergesettle.go","lineNumber":609,"sourceCode":"// It does NOT trust the primary key as proof of a shared edge. With deterministic\n// ids the same edge has the same id on every clone, but an issue rename can leave a\n// row's surrogate id stale (depid.New(oldID, target)) while issue_id/target have\n// already moved (#4259 finding 2), so two genuinely different edges could collide on\n// one id. We therefore verify the natural identity — issue_id and the resolved\n// target — matches on both sides, and that the type matches, before declaring the\n// conflict audit-only. It returns false if any conflicted row differs in identity or\n// type, or was deleted on one side (an add/delete conflict).\nfunc dependencyConflictsAreAuditOnly(ctx context.Context, db DBConn) (bool, error) {\n\trows, err := db.QueryContext(ctx, `\n\t\tSELECT our_id, their_id,\n\t\t       our_issue_id, their_issue_id,\n\t\t       our_depends_on_issue_id, their_depends_on_issue_id,\n\t\t       our_depends_on_wisp_id, their_depends_on_wisp_id,\n\t\t       our_depends_on_external, their_depends_on_external,\n\t\t       our_type, their_type\n\t\tFROM dolt_conflicts_dependencies`)\n\tif err != nil {\n\t\treturn false, fmt.Errorf(\"query dependency conflicts: %w\", err)\n\t}\n\tdefer rows.Close()\n\n\tfor rows.Next() {\n\t\tvar (\n\t\t\tourID, theirID             sql.NullString\n\t\t\tourIssue, theirIssue       sql.NullString\n\t\t\tourDepIssue, theirDepIssue sql.NullString\n\t\t\tourDepWisp, theirDepWisp   sql.NullString\n\t\t\tourDepExt, theirDepExt     sql.NullString\n\t\t\tourType, theirType         sql.NullString\n\t\t)\n\t\tif err := rows.Scan(&ourID, &theirID, &ourIssue, &theirIssue,\n\t\t\t&ourDepIssue, &theirDepIssue, &ourDepWisp, &theirDepWisp,\n\t\t\t&ourDepExt, &theirDepExt, &ourType, &theirType); err != nil {\n\t\t\treturn false, fmt.Errorf(\"scan dependency conflict: %w\", err)\n\t\t}\n\t\t// One side deleted the edge (add/delete conflict): leave for the operator.","sourceCodeStart":591,"sourceCodeEnd":627,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/versioncontrolops/mergesettle.go#L591-L627","documentation":"dependencyConflictsAreAuditOnly queries dolt_conflicts_dependencies to decide whether every dependency-table conflict is the same logical edge differing only in audit fields (safe to auto-resolve) or a real add/delete conflict (needs an operator). This error wraps any SQL failure of that SELECT — the audit check itself failed, so the caller conservatively treats the conflicts as non-auto-resolvable.","triggerScenarios":"TryAutoResolveMergeConflicts calls dependencyConflictsAreAuditOnly during a merge with conflicts in the dependencies table, and the SELECT against dolt_conflicts_dependencies fails: the conflict table does not exist (no merge state / different Dolt version), the schema lacks expected our_/their_ columns, or the connection dropped mid-query.","commonSituations":"Running against an older/newer Dolt whose dolt_conflicts_dependencies schema differs; query executed outside an active merge so the conflicts table is absent; transient network disconnect to the Dolt server mid-merge settlement.","solutions":["Verify an active merge exists (dolt_status shows conflicts) before the audit query runs; the dolt_conflicts_dependencies table only exists during a conflicted merge.","Compare the local dolt_conflicts_dependencies schema (DESCRIBE) against the column list the query selects; align the query or upgrade Dolt.","Check connectivity to the Dolt server and retry if the error is a transient driver/network failure.","Read the wrapped inner error — unknown table vs unknown column vs connection error each point to a different fix."],"exampleFix":"// before\nrows, err := db.QueryContext(ctx, \"SELECT ... FROM dolt_conflicts_dependencies\")\nif err != nil {\n\treturn false, fmt.Errorf(\"query dependency conflicts: %w\", err)\n}\n// after\nrows, err := db.QueryContext(ctx, \"SELECT ... FROM dolt_conflicts_dependencies\")\nif err != nil {\n\tif isUnknownTableErr(err) {\n\t\treturn false, nil // no merge conflict state: nothing audit-only to check\n\t}\n\treturn false, fmt.Errorf(\"query dependency conflicts: %w\", err)\n}","handlingStrategy":"fallback","validationCode":"var inMerge bool\nerr := db.QueryRowContext(ctx, \"SELECT COUNT(*) > 0 FROM dolt_status WHERE staged = 0 AND status LIKE '%conflict%'\").Scan(&inMerge)\n// only run dependencyConflictsAreAuditOnly when conflicts actually exist","typeGuard":null,"tryCatchPattern":"auditOnly, err := dependencyConflictsAreAuditOnly(ctx, db)\nif err != nil {\n\tif isUnknownTableErr(err) { // dolt_conflicts_dependencies absent: no active conflict state\n\t\tauditOnly = false // conservative fallback: leave conflicts for operator\n\t} else if isTransientNetErr(err) {\n\t\tauditOnly, err = dependencyConflictsAreAuditOnly(ctx, db) // retry once\n\t}\n}","preventionTips":["Treat any audit-query failure as 'not audit-only' — never auto-resolve on an unknown answer.","Check that an active merge with dependency conflicts exists before querying the conflicts table.","Handle unknown-table errors distinctly from unknown-column errors; they imply different Dolt-version fixes.","Pin the Dolt version in your environment so conflict-table schemas stay stable."],"tags":["dolt","sql","merge-conflicts","query"],"backgroundTag":"dolt-conflicts-query-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}