{"record":{"id":"a297fffa629b2349","repo":"gastownhall/beads","slug":"a-s-conflict-was-not-cleared-no-conflict-row-del","errorCode":null,"errorMessage":"a %s conflict was not cleared (no conflict row deleted)","messagePattern":"a (.+?) conflict was not cleared \\(no conflict row deleted\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/storage/versioncontrolops/automerge.go","lineNumber":719,"sourceCode":"\tfor _, row := range plan {\n\t\tpreds := make([]string, 0, len(row.columns))\n\t\targs := make([]any, 0, len(row.columns))\n\t\tfor i, k := range row.columns {\n\t\t\tv := row.values[i]\n\t\t\tif v == nil {\n\t\t\t\treturn fmt.Errorf(\"unexpected %s conflict row with no our_%s (safety check bypassed)\", table, k)\n\t\t\t}\n\t\t\tpreds = append(preds, \"`our_\"+k+\"` = ?\")\n\t\t\targs = append(args, v)\n\t\t}\n\t\t//nolint:gosec // table and key columns come from the unionConflictKeyColumns allowlist.\n\t\tstmt := \"DELETE FROM `dolt_conflicts_\" + table + \"` WHERE \" + strings.Join(preds, \" AND \")\n\t\tres, err := db.ExecContext(ctx, stmt, args...)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"clear %s conflict: %w\", table, err)\n\t\t}\n\t\tif n, err := res.RowsAffected(); err == nil && n == 0 {\n\t\t\treturn fmt.Errorf(\"a %s conflict was not cleared (no conflict row deleted)\", table)\n\t\t}\n\t}\n\treturn nil\n}\n","sourceCodeStart":701,"sourceCodeEnd":724,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/versioncontrolops/automerge.go#L701-L724","documentation":"The DELETE ran successfully but deleted zero rows from dolt_conflicts_<table>, meaning the validated conflict row vanished between the check pass and the resolution. Deleting the conflict row is what marks it settled in dolt, so zero deletions mean the conflict could not be cleared and the resolution is refused rather than silently 'succeeding'.","triggerScenarios":"Another session resolved or deleted the same conflict rows after unionConflictsAreSafe loaded the plan but before resolveUnionConflicts executed its DELETE; a concurrent dolt_conflicts_resolve or merge cleared the table; the key values in the plan no longer match any row.","commonSituations":"Two agents or two machines auto-resolving the same repo simultaneously; a user ran dolt_conflicts_resolve --ours while auto-merge was in flight; the merge was retried and the first attempt already cleared the conflicts.","solutions":["Re-run TryAutoResolveMergeConflicts so a fresh plan is built from current conflict state — the stale plan's rows are already gone.","Serialize merge resolution: hold the repo lock or ensure only one process auto-resolves at a time.","Check dolt conflict status to confirm the conflicts are actually resolved before treating this as a failure.","If it recurs, look for concurrent automation (cron, CI, another agent session) touching the same working set."],"exampleFix":"// before — retrying resolution with the same stale plan\n if n == 0 { return fmt.Errorf(\"a %s conflict was not cleared (no conflict row deleted)\", table) }\n// after — rebuild the plan from live state and retry once\n if n == 0 {\n     freshPlan, safe, err := unionConflictsAreSafe(ctx, db, table)\n     if err != nil { return err }\n     if safe { return resolveUnionConflicts(ctx, db, table, freshPlan) }\n     return nil // conflicts already gone or no longer auto-resolvable\n }","handlingStrategy":"retry","validationCode":"// verify conflict rows still exist before deleting\nfor _, row := range plan {\n\tvar n int\n\targs := row.values\n\tif err := db.QueryRowContext(ctx,\n\t\t\"SELECT COUNT(*) FROM `dolt_conflicts_\"+table+\"` WHERE \"+keyPreds(row.columns), args...).Scan(&n);\n\t\terr == nil && n == 0 {\n\t\t// stale plan: rebuild before resolving\n\t}\n}","typeGuard":null,"tryCatchPattern":"if err := resolveUnionConflicts(ctx, db, table, plan); err != nil {\n\tif strings.Contains(err.Error(), \"was not cleared\") {\n\t\t// plan is stale — rebuild from live conflict state and retry once\n\t\tfreshPlan, safe, err2 := unionConflictsAreSafe(ctx, db, table)\n\t\tif err2 == nil && safe {\n\t\t\treturn resolveUnionConflicts(ctx, db, table, freshPlan)\n\t\t}\n\t\treturn nil // conflicts already gone\n\t}\n\treturn err\n}","preventionTips":["Ensure only one process/session auto-resolves a repo's conflicts at a time.","Rebuild the plan immediately before resolution; don't cache plans across operations.","After the error, verify conflict state — it usually means another resolver already won.","Avoid scheduling overlapping auto-merge jobs (cron/CI/agent sessions) on the same working set."],"tags":["go","merge-conflicts","race-condition","dolt"],"backgroundTag":"conflict-row-vanished","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}