gastownhall/beads · error

counting nonlocal frozen rows: %w

Error message

counting nonlocal frozen rows: %w

What it means

anyNonlocalFrozenRowPresent counts the four frozen dolt_nonlocal_tables rows (wisps, wisp_*, repo_mtimes, local_metadata) to decide whether a 0040/0041 heal is needed. This error wraps a SQL failure of that COUNT query — typically the table missing entirely or a connection error. Without the count the repair cannot tell if the database took the partial-apply brick.

Source

Thrown at internal/storage/schema/migration_repairs.go:99

// if the edit staged nothing.
func commitNonlocalRepair(ctx context.Context, db DBConn, message string) error {
	if err := DrainCall(ctx, db, "CALL DOLT_ADD(?)", nonlocalTablesName); err != nil {
		return fmt.Errorf("staging %s: %w", nonlocalTablesName, err)
	}
	return DrainCall(ctx, db, "CALL DOLT_COMMIT('-m', ?, '--skip-empty')", message)
}

// anyNonlocalFrozenRowPresent reports whether any of 0040's four
// dolt_nonlocal_tables rows currently exists (in the working set), the signal
// the version-40/41 repairs use to decide whether a heal is needed. Guarding on
// it keeps both repairs a strict no-op on the common (non-partial) path, so a
// fresh init reaches 0040/0041 having done no repair work at all — the repairs
// only ever touch a database that actually took the partial-apply brick.
func anyNonlocalFrozenRowPresent(ctx context.Context, db DBConn) (bool, error) {
	var count int
	if err := db.QueryRowContext(ctx,
		"SELECT COUNT(*) FROM dolt_nonlocal_tables WHERE table_name IN "+nonlocalFrozenRowsInList).Scan(&count); err != nil {
		return false, fmt.Errorf("counting nonlocal frozen rows: %w", err)
	}
	return count > 0, nil
}

// repairPartial0040NonlocalInsert heals a partially-applied migration 0040 so
// its shipped body can replay. 0040 bare-INSERTs four dolt_nonlocal_tables rows,
// each paired with its own CALL DOLT_COMMIT. Over a shared sql-server a transient
// ("busy buffer" -> "bad connection") can leave some rows committed while the
// schema_migrations version row never records, so the init retry loop re-runs
// 0040 from the top and the bare INSERT dies on "duplicate primary key given:
// [wisps]", bricking the database. 0040 is a shipped, content-hashed migration
// and cannot be edited (see the file header), so instead clear any of those four
// rows before the replay and commit the removal, leaving 0040's INSERT+COMMIT
// pairs a clean, real diff. No-op when 0040 never partially applied.
func repairPartial0040NonlocalInsert(ctx context.Context, db DBConn) error {
	present, err := anyNonlocalFrozenRowPresent(ctx, db)
	if err != nil {
		return err

View on GitHub (pinned to 71377f2769)

Solutions

  1. Retry bd init after confirming the Dolt server is reachable
  2. If the wrapped error is "table not found: dolt_nonlocal_tables", the database predates 0040 and repair should be a no-op — verify the migration cursor
  3. Run bd doctor to assess database health
  4. If the table should exist but is missing, restore from a clone/backup
Defensive patterns

Strategy: try-catch

Validate before calling

// confirm dolt_nonlocal_tables exists before repair logic runs
var n int
err := db.QueryRowContext(ctx, `SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES
  WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'dolt_nonlocal_tables'`).Scan(&n)
// n == 0 means pre-0040 database: repair is legitimately a no-op

Try / catch

present, err := anyNonlocalFrozenRowPresent(ctx, db)
if err != nil {
    if isTableNotFound(err) {
        return nil // pre-0040 database: nothing to repair
    }
    return err
}

Prevention

When it happens

Trigger: SELECT COUNT(*) FROM dolt_nonlocal_tables fails because the table does not exist (fresh/pre-0040 database or drifted clone), or the connection to the Dolt server drops mid-query during bd init.

Common situations: Upgrading a very old or drifted clone whose schema predates 0040; shared sql-server outage during init; manually deleted schema tables.

Related errors


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