gastownhall/beads · error

query dependency conflicts: %w

Error message

query dependency conflicts: %w

What it means

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.

Source

Thrown at internal/storage/versioncontrolops/mergesettle.go:609

// It does NOT trust the primary key as proof of a shared edge. With deterministic
// ids the same edge has the same id on every clone, but an issue rename can leave a
// row's surrogate id stale (depid.New(oldID, target)) while issue_id/target have
// already moved (#4259 finding 2), so two genuinely different edges could collide on
// one id. We therefore verify the natural identity — issue_id and the resolved
// target — matches on both sides, and that the type matches, before declaring the
// conflict audit-only. It returns false if any conflicted row differs in identity or
// type, or was deleted on one side (an add/delete conflict).
func dependencyConflictsAreAuditOnly(ctx context.Context, db DBConn) (bool, error) {
	rows, err := db.QueryContext(ctx, `
		SELECT our_id, their_id,
		       our_issue_id, their_issue_id,
		       our_depends_on_issue_id, their_depends_on_issue_id,
		       our_depends_on_wisp_id, their_depends_on_wisp_id,
		       our_depends_on_external, their_depends_on_external,
		       our_type, their_type
		FROM dolt_conflicts_dependencies`)
	if err != nil {
		return false, fmt.Errorf("query dependency conflicts: %w", err)
	}
	defer rows.Close()

	for rows.Next() {
		var (
			ourID, theirID             sql.NullString
			ourIssue, theirIssue       sql.NullString
			ourDepIssue, theirDepIssue sql.NullString
			ourDepWisp, theirDepWisp   sql.NullString
			ourDepExt, theirDepExt     sql.NullString
			ourType, theirType         sql.NullString
		)
		if err := rows.Scan(&ourID, &theirID, &ourIssue, &theirIssue,
			&ourDepIssue, &theirDepIssue, &ourDepWisp, &theirDepWisp,
			&ourDepExt, &theirDepExt, &ourType, &theirType); err != nil {
			return false, fmt.Errorf("scan dependency conflict: %w", err)
		}
		// One side deleted the edge (add/delete conflict): leave for the operator.

View on GitHub (pinned to 71377f2769)

Solutions

  1. 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.
  2. Compare the local dolt_conflicts_dependencies schema (DESCRIBE) against the column list the query selects; align the query or upgrade Dolt.
  3. Check connectivity to the Dolt server and retry if the error is a transient driver/network failure.
  4. Read the wrapped inner error — unknown table vs unknown column vs connection error each point to a different fix.

Example fix

// before
rows, err := db.QueryContext(ctx, "SELECT ... FROM dolt_conflicts_dependencies")
if err != nil {
	return false, fmt.Errorf("query dependency conflicts: %w", err)
}
// after
rows, err := db.QueryContext(ctx, "SELECT ... FROM dolt_conflicts_dependencies")
if err != nil {
	if isUnknownTableErr(err) {
		return false, nil // no merge conflict state: nothing audit-only to check
	}
	return false, fmt.Errorf("query dependency conflicts: %w", err)
}
Defensive patterns

Strategy: fallback

Validate before calling

var inMerge bool
err := db.QueryRowContext(ctx, "SELECT COUNT(*) > 0 FROM dolt_status WHERE staged = 0 AND status LIKE '%conflict%'").Scan(&inMerge)
// only run dependencyConflictsAreAuditOnly when conflicts actually exist

Try / catch

auditOnly, err := dependencyConflictsAreAuditOnly(ctx, db)
if err != nil {
	if isUnknownTableErr(err) { // dolt_conflicts_dependencies absent: no active conflict state
		auditOnly = false // conservative fallback: leave conflicts for operator
	} else if isTransientNetErr(err) {
		auditOnly, err = dependencyConflictsAreAuditOnly(ctx, db) // retry once
	}
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/343c6139180b5c67. Report an issue: GitHub.