{"record":{"id":"c74408a1e63d9574","repo":"gastownhall/beads","slug":"conflict-table-dolt-conflicts-s-has-no-our-s-the","errorCode":null,"errorMessage":"conflict table dolt_conflicts_%s has no our_%s/their_%s column","messagePattern":"conflict table dolt_conflicts_(.+?) has no our_(.+?)/their_(.+?) column","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/versioncontrolops/conflicts.go","lineNumber":377,"sourceCode":"\tq := fmt.Sprintf(\"SELECT COUNT(*) FROM `%s` WHERE `%s` = ?\", table, keyCol)\n\tvar n int\n\tif err := db.QueryRowContext(ctx, q, key).Scan(&n); err != nil {\n\t\treturn false, err\n\t}\n\treturn n > 0, nil\n}\n\n// resolveOneConflictRow applies strategy to a single modify/modify row.\n//\n// \"ours\" is dolt's manual-resolution path: the working set already holds our\n// values, so deleting the conflict row *is* the resolution. \"theirs\" first\n// writes their values over ours, then deletes the conflict row — the order\n// matters, since the delete is what tells dolt the row is settled.\nfunc resolveOneConflictRow(ctx context.Context, db DBConn, table, keyCol, key, strategy string, row rawConflictRow) error {\n\tourKey, ourOK := row.value(\"our\", keyCol)\n\ttheirKey, theirOK := row.value(\"their\", keyCol)\n\tif !ourOK || !theirOK {\n\t\treturn fmt.Errorf(\"conflict table dolt_conflicts_%s has no our_%s/their_%s column\", table, keyCol, keyCol)\n\t}\n\tif ourKey == nil || theirKey == nil {\n\t\t// delete/modify (one side removed the row) or add/add against a\n\t\t// missing key: refuse by name. Row-level ours/theirs would silently\n\t\t// resurrect or destroy a row the operator never looked at.\n\t\treturn fmt.Errorf(\"conflict for %s %s is not a modify/modify conflict (one side has no row); \"+\n\t\t\t\"resolve it with a whole-table strategy or edit the row directly\", table, key)\n\t}\n\n\tif strategy == ConflictStrategyTheirs {\n\t\tnames, vals := row.theirFields(keyCol)\n\t\tif len(names) == 0 {\n\t\t\treturn fmt.Errorf(\"conflict for %s %s carries no their_* data columns\", table, key)\n\t\t}\n\t\tsets := make([]string, len(names))\n\t\targs := make([]any, 0, len(names)+1)\n\t\tfor i, n := range names {\n\t\t\t// Column names are interpolated (MySQL cannot bind an","sourceCodeStart":359,"sourceCodeEnd":395,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/versioncontrolops/conflicts.go#L359-L395","documentation":"resolveOneConflictRow could not find the expected our_<keyCol> and/or their_<keyCol> columns in the scanned conflict row. Dolt's conflict tables expose each side's key as our_/their_-prefixed columns; their absence means the conflict table shape differs from what row-level resolution requires (schema drift, dolt version difference, or a corrupted conflict table). Row-level resolution cannot proceed without both key values.","triggerScenarios":"ResolveConflictRows -> resolveOneConflictRow checks row.value(\"our\", keyCol)/row.value(\"their\", keyCol) after a `SELECT *` on dolt_conflicts_<table>; the returned column set lacks one of the key columns, e.g. after a schema merge that renamed/removed the key column or a dolt version with a different conflict-table layout.","commonSituations":"Peer merged a schema change that renamed the key column while a merge was open; upgrading dolt sql-server while conflicts exist; manually manipulating dolt_conflicts_<table> previously.","solutions":["Abort the merge (`CALL dolt_merge_conflicts_cleanup` / roll back) and redo the merge after schemas are aligned","Check both branches' schemas: `SHOW CREATE TABLE` on base and both branches to spot the key-column divergence","Upgrade or align the dolt version between peers before merging","Resolve at whole-table level and then reconcile the key column manually"],"exampleFix":"null","handlingStrategy":"validation","validationCode":"// confirm both key columns exist before row-level resolution\ncols, _ := conflictTableColumns(ctx, db, table)\nif !slices.Contains(cols, \"our_\"+keyCol) || !slices.Contains(cols, \"their_\"+keyCol) {\n    return fmt.Errorf(\"key column %s diverged between branches; reconcile schema first\", keyCol)\n}","typeGuard":null,"tryCatchPattern":"err := resolveOne(ctx, db, table, keyCol, key, strategy)\nif err != nil && strings.Contains(err.Error(), \"has no our_\") {\n    return abortMergeAndReconcileSchema(ctx, db, table)\n}\nreturn err","preventionTips":["Freeze schema changes while a merge with conflicts is open","Compare branch schemas before pulling from peers","Align dolt versions across all peers","Recreate key columns via migrations, never ad-hoc renames mid-merge"],"tags":["database","dolt","schema-conflict","conflict-resolution"],"backgroundTag":"conflict-schema-mismatch","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}