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

  1. Inspect the wrapped %w error for 'expected N destination arguments' (column count drift) vs conversion errors.
  2. Run the query manually to see the actual columns returned by your Dolt version.
  3. Upgrade beads to a version matching your Dolt engine's violations schema.
  4. 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

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


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