gastownhall/beads · error

iterate constraint violations: %w

Error message

iterate constraint violations: %w

What it means

After scanning dolt_constraint_violations rows, rows.Err() returned non-nil — the result-set iteration failed mid-stream (connection drop, context cancellation, or embedded engine error). Like its schema-conflicts sibling, this is a transport/engine failure while reading the violation list, not bad data.

Source

Thrown at internal/storage/versioncontrolops/conflicts.go:537

	rows, err := db.QueryContext(ctx,
		"SELECT `table`, num_violations FROM dolt_constraint_violations WHERE num_violations > 0")
	if err != nil {
		if isMissingSystemTable(err) {
			return nil, nil
		}
		return nil, fmt.Errorf("query constraint violations: %w", err)
	}
	defer func() { _ = rows.Close() }()
	var out []storage.ConstraintViolation
	for rows.Next() {
		var v storage.ConstraintViolation
		if err := rows.Scan(&v.Table, &v.Count); err != nil {
			return nil, fmt.Errorf("scan constraint violation: %w", err)
		}
		out = append(out, v)
	}
	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("iterate constraint violations: %w", err)
	}
	return out, nil
}

// isMissingSystemTable reports whether err is dolt/MySQL's "table does not
// exist". Matched on the message because the embedded engine and the MySQL
// driver report it as different error types.
func isMissingSystemTable(err error) bool {
	if err == nil {
		return false
	}
	msg := strings.ToLower(err.Error())
	return strings.Contains(msg, "table not found") ||
		strings.Contains(msg, "doesn't exist") ||
		strings.Contains(msg, "does not exist") ||
		strings.Contains(msg, "unknown table")
}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Retry GetMergeBlockers on a fresh connection/context; mid-iteration failures are typically transient.
  2. Increase context and driver timeouts when the violations table is large or the server is loaded.
  3. Check server-side logs for the disconnect/error that terminated the result set.
  4. Stabilize the connection (pool settings, keepalives) if this recurs during long merge-resolution sessions.

Example fix

// before: one attempt with a tight deadline
v, err := ops.GetMergeBlockers(ctx, db)
// after: retry with an extended deadline on transient failure
attempt := func() (storage.MergeBlockers, error) {
  c, cancel := context.WithTimeout(ctx, 90*time.Second)
  defer cancel()
  return ops.GetMergeBlockers(c, db)
}
v, err := attempt()
if err != nil && isTransient(err) { v, err = attempt() }
Defensive patterns

Strategy: retry

Validate before calling

if err := db.PingContext(ctx); err != nil { return err }
ctx, cancel := context.WithTimeout(ctx, 90*time.Second); defer cancel()

Try / catch

if err != nil && strings.Contains(err.Error(), "iterate constraint violations") {
  time.Sleep(2 * time.Second)
  blockers, err = ops.GetMergeBlockers(freshCtx, freshDB)
}

Prevention

When it happens

Trigger: GetMergeBlockers iterating dolt_constraint_violations when the connection drops, the context deadline expires, sql-server closes the result, or the embedded engine errors while reading a large violation set.

Common situations: Slow servers with large violation lists and short context timeouts; flaky network to a remote dolt sql-server; connection-pool reclamation mid-query in long-lived services.

Related errors


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