gastownhall/beads · error
scan constraint violation: %w
Error message
scan constraint violation: %w
What it means
While scanning rows of the dolt_constraint_violations listing, a row could not be read into a single string column (the table name). This indicates the rowset's column shape differs from expected — the engine returned extra or differently-typed columns. Scanning stops and the partial table list is discarded with this wrapped error.
Source
Thrown at internal/storage/versioncontrolops/mergesettle.go:913
return false, true, nil
}
return true, true, nil
}
// constraintViolationTables lists the tables with outstanding constraint
// violations in the working set.
func constraintViolationTables(ctx context.Context, db DBConn) ([]string, error) {
rows, err := db.QueryContext(ctx,
"SELECT `table` FROM dolt_constraint_violations WHERE num_violations > 0")
if err != nil {
return nil, fmt.Errorf("query constraint violations: %w", err)
}
defer rows.Close()
var tables []string
for rows.Next() {
var t string
if err := rows.Scan(&t); err != nil {
return nil, fmt.Errorf("scan constraint violation: %w", err)
}
tables = append(tables, t)
}
return tables, rows.Err()
}
// violationsAreIssueFKOnly reports whether every constraint violation recorded
// for table is a foreign-key violation referencing issues — the only class the
// cascade repair understands. violation_info is Dolt's JSON descriptor; its
// ReferencedTable names the FK's parent.
func violationsAreIssueFKOnly(ctx context.Context, db DBConn, table string) (bool, error) {
// table is from the fixed fkCascadeRepairDeletes allowlist, never user input.
//nolint:gosec // G202: hardcoded table name.
rows, err := db.QueryContext(ctx,
"SELECT violation_type, violation_info FROM dolt_constraint_violations_"+table)
if err != nil {
return false, fmt.Errorf("query %s constraint violations: %w", table, err)
}View on GitHub (pinned to 71377f2769)
Solutions
- Inspect the wrapped %w error for 'expected N destination arguments' (column count drift) vs conversion errors.
- Run the query manually to see the actual columns returned by your Dolt version.
- Upgrade beads to a version matching your Dolt engine's violations schema.
- Pin the Dolt engine version beads was built and tested against.
Example fix
// before
var t string
if err := rows.Scan(&t); err != nil {
return nil, fmt.Errorf("scan constraint violation: %w", err)
}
// after: scan by column count flexibility
var t string
cols, _ := rows.Columns()
if len(cols) == 1 {
err = rows.Scan(&t)
} else {
var extra sql.RawBytes
args := []any{&t, &extra}
err = rows.Scan(args...) // adapt to engine layout
}
if err != nil {
return nil, fmt.Errorf("scan constraint violation: %w", err)
} Defensive patterns
Strategy: try-catch
Validate before calling
cols, _ := db.Query("SELECT `table` FROM dolt_constraint_violations LIMIT 0")
// inspect cols.Columns() to confirm a single string column before scanning Try / catch
tables, err := constraintViolationTables(ctx, db)
if err != nil && strings.Contains(err.Error(), "scan constraint violation") {
// system-table schema drift: fall back to manual inspection
return manualViolationListing()
} Prevention
- Re-check violations-table layout after Dolt upgrades
- Pin engine versions in deployment
- Avoid mixing server and embedded engines against the same repo
When it happens
Trigger: dolt_constraint_violations returns rows whose shape doesn't match one string column — e.g. Dolt changed the system table's schema (added columns) or a NULL table name is returned.
Common situations: Engine upgrade changing the violations table layout; mixed server/embedded behaviors; corrupted merge metadata row.
Related errors
- scan %s constraint violation: %w
- iter dependents: scan: %w
- iter issues: scan: %w
- query constraint violations: %w
- scan constraint violation: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/021805afc065df05.
Report an issue: GitHub.