{"record":{"id":"dc12c9959010a350","repo":"gastownhall/beads","slug":"apply-merged-values-for-issue-v-w","errorCode":null,"errorMessage":"apply merged values for issue %v: %w","messagePattern":"apply merged values for issue (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/versioncontrolops/automerge.go","lineNumber":602,"sourceCode":"\t\t}\n\t\tif len(m.columns) > 0 {\n\t\t\tsets := make([]string, len(m.columns))\n\t\t\targs := make([]any, 0, len(m.columns)+1)\n\t\t\tfor i, col := range m.columns {\n\t\t\t\t// MySQL cannot bind an identifier and a peer's schema merge can\n\t\t\t\t// extend the conflict table's columns, so gate every name the\n\t\t\t\t// same way the table name is gated.\n\t\t\t\tif err := ValidateConflictTable(col); err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"refusing to write unexpected column %q of issues: %w\", col, err)\n\t\t\t\t}\n\t\t\t\tsets[i] = fmt.Sprintf(\"`%s` = ?\", col)\n\t\t\t\targs = append(args, m.values[i])\n\t\t\t}\n\t\t\targs = append(args, m.ourKey)\n\t\t\tstmt := fmt.Sprintf(\"UPDATE `issues` SET %s WHERE `%s` = ?\", strings.Join(sets, \", \"), issuesKeyColumn) //nolint:gosec // identifiers validated above\n\t\t\tres, err := db.ExecContext(ctx, stmt, args...)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"apply merged values for issue %v: %w\", m.ourKey, err)\n\t\t\t}\n\t\t\t// Zero rows would mean the row we planned against is gone —\n\t\t\t// another session deleted it between the read and the write, and\n\t\t\t// clearing the conflict now would discard their side undetectably.\n\t\t\t// But RowsAffected is rows CHANGED, not rows MATCHED: the DSN does\n\t\t\t// not set clientFoundRows (doltutil/dsn.go), so a write the backend\n\t\t\t// normalizes to the bytes already stored also reports zero. Only a\n\t\t\t// follow-up existence check can tell \"vanished\" from \"no-op\".\n\t\t\tif n, err := res.RowsAffected(); err != nil || n == 0 {\n\t\t\t\tpresent, err := conflictTargetStillPresent(ctx, db, \"issues\", issuesKeyColumn, m.ourKey)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"confirm issue %v still exists after writing merged values: %w\", m.ourKey, err)\n\t\t\t\t}\n\t\t\t\tif !present {\n\t\t\t\t\treturn fmt.Errorf(\"merged values for issue %v matched no row (was it deleted concurrently?); conflict left unresolved\", m.ourKey)\n\t\t\t\t}\n\t\t\t}\n\t\t}","sourceCodeStart":584,"sourceCodeEnd":620,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/versioncontrolops/automerge.go#L584-L620","documentation":"This error wraps the driver/database error returned when an UPDATE that writes field-merged values over an issue's working-set row fails inside the dolt manual conflict-resolution path. resolveIssuesFieldMerge writes merged cells directly to the `issues` table (DOLT_CONFLICTS_RESOLVE cannot express per-cell merges), so any SQL failure — connection loss, schema mismatch, type error, lock timeout — is surfaced here tagged with the issue id. The conflict is left unresolved; the caller (TryAutoResolveMergeConflicts) aborts the auto-merge pass.","triggerScenarios":"db.ExecContext on `UPDATE issues SET ... WHERE <key> = ?` fails during auto conflict resolution — e.g. the Dolt/MySQL connection dropped mid-merge, a column added on the peer branch has an incompatible type so a merged value cannot bind, the database is read-only/locked by another process, or the working-set schema diverged from the conflict-table schema the plan was built from.","commonSituations":"Two `bd` sessions merging concurrently while one connection is killed or times out; a peer schema migration added a column and the merged value's Go type (e.g. []byte vs int64) cannot be bound; running against a replica or read-only database; Dolt server restarted during a long merge.","solutions":["Re-run `bd dolt pull`/merge after confirming the database is reachable and writable; the conflict row is untouched so the merge can be retried.","Check the wrapped driver error (%w) for type-mismatch on a specific column; if a peer schema change added it, re-sync schemas and retry.","Verify no other process holds a lock on the Dolt database (e.g. a stale server or second `bd` doing schema work) and retry.","If the error repeats, resolve the conflict manually (DOLT_CONFLICTS_RESOLVE --ours/--theirs or editing the row) and re-run.","Confirm the user the connection uses has UPDATE privilege on `issues` and the working set is not read-only."],"exampleFix":"// before: plan built once, then applied without any schema/type check on values\nargs = append(args, m.values[i])\nres, err := db.ExecContext(ctx, stmt, args...)\n// after: coerce merged values through the same normalization used for comparison before binding\nfor i, col := range m.columns {\n    m.values[i] = conflictCellsNormalize(m.values[i])\n}\nres, err := db.ExecContext(ctx, stmt, args...)","handlingStrategy":"try-catch","validationCode":"// before triggering auto-merge, check connectivity and writability\nvar live int\nif err := db.QueryRowContext(ctx, \"SELECT 1\").Err; err != nil {\n    return fmt.Errorf(\"database unreachable before merge: %w\", err)\n}\nif _, err := db.ExecContext(ctx, \"SELECT COUNT(*) FROM `issues` LIMIT 1\"); err != nil {\n    return fmt.Errorf(\"issues table not readable/schema mismatch: %w\", err)\n}","typeGuard":"func isDriverError(err error) bool {\n    var de interface{ Error() string; Unwrap() error }\n    return errors.As(err, &de) && strings.Contains(err.Error(), \"apply merged values\")\n}","tryCatchPattern":"if err := TryAutoResolveMergeConflicts(ctx, db); err != nil {\n    var wrapped interface{ Unwrap() error }\n    if errors.As(err, &wrapped) {\n        log.Printf(\"auto-merge failed for issue (driver: %v); conflict left unresolved — retry or resolve manually\", errors.Unwrap(err))\n    }\n    // safe fallback: conflict row remains; a later pull can retry\n    return fallbackManualResolve(ctx, db)\n}","preventionTips":["Keep the Dolt connection stable; run merges against a local/embedded database when the network is unreliable","Apply peer schema migrations before merging so conflict-table columns match the working-set schema","Ensure the merge user has UPDATE privileges on `issues` and the database is not read-only","Avoid running merges concurrently with schema-changing commands"],"tags":["database","dolt","merge-conflict","sql-update","storage"],"backgroundTag":"sql-update-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}