gastownhall/beads · warning

uow: team-server schema check: %w

Error message

uow: team-server schema check: %w

What it means

After the USE succeeds, verifyTeamServerSchema calls checkTeamServerSchema to verify the team-server database's schema version matches this binary. A serialization-class failure there is wrapped as 'uow: team-server schema check: %w' and returned bare so the backoff loop retries; non-serialization failures are terminal (returned unwrapped as permanent).

Source

Thrown at internal/storage/uow/dolt_sql_provider.go:256

// verifyTeamServerSchema is the team-server open path: the schema is owned by
// beads-team-server (bts), so bd never creates the database or migrates. It
// attaches to the existing database and verifies the schema version, then the
// project identity — identity is checked only after the schema check proves the
// metadata table exists at this binary's version.
func (p *doltSQLProvider) verifyTeamServerSchema(ctx context.Context, conn *sql.Conn, database string) error {
	ddl := db.NewDDLSQLRepository(conn)
	if err := ddl.UseDatabase(ctx, database); err != nil {
		if isSerializationError(err) {
			return fmt.Errorf("uow: switching to database: %w", err)
		}
		return backoff.Permanent(fmt.Errorf(
			"uow: database %q not found — the schema is managed by beads-team-server; ask your operator to run 'bts init' first: %w",
			database, err))
	}
	if err := checkTeamServerSchema(ctx, conn, database); err != nil {
		if isSerializationError(err) {
			return fmt.Errorf("uow: team-server schema check: %w", err)
		}
		return backoff.Permanent(err)
	}
	if err := checkTeamServerIdentity(ctx, conn, database, p.expectedProjectID); err != nil {
		if isSerializationError(err) {
			return fmt.Errorf("uow: team-server identity check: %w", err)
		}
		return backoff.Permanent(err)
	}
	return nil
}

// attachPreviewDatabase is the preview open path: attach to the database that is
// already there and stop. No CreateDatabase, no MigrateUpWithLock — a --dry-run
// or --inspect that migrated the workspace before rendering its plan would be the
// exact side effect the flag exists to prevent.
func (p *doltSQLProvider) attachPreviewDatabase(ctx context.Context, conn *sql.Conn, database string) error {
	ddl := db.NewDDLSQLRepository(conn)

View on GitHub (pinned to 71377f2769)

Solutions

  1. Retry — backoff will re-run the check once concurrent writes settle.
  2. Ensure 'bts init' (or the schema upgrade) fully completed before clients connect.
  3. Check the team server's schema version is compatible with this bd binary.
  4. Inspect the wrapped cause if the check keeps failing.
Defensive patterns

Strategy: retry

Validate before calling

// confirm the team server's schema version is current before connecting clients
var version string
err := adminConn.QueryRowContext(ctx,
    "SELECT value FROM metadata WHERE key = 'schema_version'").Scan(&version)
if err != nil { return fmt.Errorf("cannot read team-server schema version: %w", err) }
if version != schema.ExpectedVersion {
    return fmt.Errorf("team-server schema %s != binary expects %s; run bts upgrade", version, schema.ExpectedVersion)
}

Type guard

if uow.IsSerializationError(err) { /* transient check failure — retryable */ }

Try / catch

err := provider.Open(ctx, cfg)
if err != nil {
    if uow.IsSerializationError(err) {
        // team-server metadata contended — retry with backoff
        return backoff.Retry(openFn, bo)
    }
    return err
}

Prevention

When it happens

Trigger: initSchemaAttempt (teamServer=true); the metadata/schema-version query inside checkTeamServerSchema fails with a serialization error on the contended shared server, e.g. while 'bts init' or an upgrade is still in flight.

Common situations: Clients connecting while the operator is mid-'bts init' or mid schema upgrade; Dolt serialization conflicts from concurrent metadata reads/writes on a loaded team server.

Related errors


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