gastownhall/beads · error

scan %s constraint violation: %w

Error message

scan %s constraint violation: %w

What it means

While inspecting per-table violation rows, a row could not be scanned into (violation_type string, violation_info any). This means the row shape or types deviate from what the two-destination Scan expects. The check aborts with this wrapped error, blocking the auto-repair (which requires proving all violations are FK-only).

Source

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

// 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)
	}
	defer rows.Close()
	for rows.Next() {
		var vtype string
		var vinfo any
		if err := rows.Scan(&vtype, &vinfo); err != nil {
			return false, fmt.Errorf("scan %s constraint violation: %w", table, err)
		}
		if vtype != "foreign key" {
			return false, nil
		}
		// Server mode returns violation_info as JSON text; the embedded engine
		// hands back the driver's native value (e.g. merge.FkCVMeta), which
		// marshals to the same JSON.
		var infoJSON []byte
		switch v := vinfo.(type) {
		case []byte:
			infoJSON = v
		case string:
			infoJSON = []byte(v)
		default:
			b, err := json.Marshal(v)
			if err != nil {
				return false, nil // unknown descriptor shape — operator decides
			}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Check the wrapped %w error for column count vs type-conversion details.
  2. Run SELECT violation_type, violation_info FROM dolt_constraint_violations_<table> manually to inspect actual shapes.
  3. Upgrade beads (or the Dolt engine) so the driver's violation_info encoding matches the code path (JSON text vs native value).
  4. Until fixed, resolve violations manually rather than via auto-repair.

Example fix

// before
var vtype string
var vinfo any
if err := rows.Scan(&vtype, &vinfo); err != nil {
    return false, fmt.Errorf("scan %s constraint violation: %w", table, err)
}
// after: accept either JSON text or native value shapes
var vtype string
var vinfo any
if err := rows.Scan(&vtype, &vinfo); err != nil {
    var raw []byte
    if serr := rows.Scan(&vtype, &raw); serr != nil {
        return false, fmt.Errorf("scan %s constraint violation: %w", table, err)
    }
    vinfo = string(raw)
}
Defensive patterns

Strategy: type-guard

Validate before calling

rows, _ := db.Query("SELECT violation_type, violation_info FROM dolt_constraint_violations_issues LIMIT 1")
cols, _ := rows.Columns()
// proceed only when len(cols) == 2

Type guard

func violationRowShapeMatches(ctx context.Context, db DBConn, table string) bool {
    rows, err := db.QueryContext(ctx, "SELECT violation_type, violation_info FROM dolt_constraint_violations_"+table+" LIMIT 1")
    if err != nil {
        return false
    }
    defer rows.Close()
    c, _ := rows.Columns()
    return len(c) == 2
}

Try / catch

ok, err := violationsAreIssueFKOnly(ctx, db, t)
if err != nil && strings.Contains(err.Error(), "scan") {
    // violation_info encoding drift: fall back to manual resolution
    return manualFKResolution(t)
}

Prevention

When it happens

Trigger: A violations row returns a violation_type that is not string-convertible or an unexpected number of columns (engine version changed violation_info encoding), causing rows.Scan to fail.

Common situations: Dolt upgrade changing violation_info from JSON text to a structured native driver value (or vice versa); server vs embedded engine returning different driver value types; corrupt violation metadata.

Related errors


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