gastownhall/beads · error
unsafe dolt status table name %q
Error message
unsafe dolt status table name %q
What it means
dirtyTableSignature interpolates a table name from dolt_status into a dolt_diff('HEAD','WORKING', '<table>') literal, so it first validates the name against doltStatusTableNameRE to prevent SQL injection through a crafted table name. A name that does not match the safe pattern yields "unsafe dolt status table name %q" and the diff is never executed.
Source
Thrown at internal/storage/schema/schema.go:862
for table := range tables {
names = append(names, table)
}
sort.Strings(names)
return names
}
func sortedSignatureTableNames(signatures map[string]string) []string {
names := make([]string, 0, len(signatures))
for table := range signatures {
names = append(names, table)
}
sort.Strings(names)
return names
}
func dirtyTableSignature(ctx context.Context, db DBConn, table string) (string, error) {
if !doltStatusTableNameRE.MatchString(table) {
return "", fmt.Errorf("unsafe dolt status table name %q", table)
}
//nolint:gosec // table comes from dolt_status; dolt_diff requires a literal table argument.
rows, err := db.QueryContext(ctx, "SELECT * FROM dolt_diff('HEAD', 'WORKING', "+sqlStringLiteral(table)+")")
if err != nil {
return "", err
}
defer rows.Close()
columns, err := rows.Columns()
if err != nil {
return "", err
}
var rowSignatures []string
for rows.Next() {
values := make([]any, len(columns))
dest := make([]any, len(columns))
for i := range values {View on GitHub (pinned to 71377f2769)
Solutions
- Find the offending table with `dolt status` in the .beads database directory — the message quotes the exact rejected name.
- Rename the table to a plain identifier (letters, digits, underscores): `dolt sql -q "RENAME TABLE \`bad name\` TO good_name"`, then retry `bd`.
- If the table is junk created by tooling, drop it: `dolt sql -q "DROP TABLE \`bad name\`"`.
- If dolt_status itself contains entries for nonexistent tables, verify against `dolt status` output and repair the working set (dolt reset --hard only if data loss is acceptable).
- If a legitimately simple table name is rejected, check your beads/Dolt version — a regex/version mismatch should be reported upstream.
Example fix
// before: a table named `we;ird'name` in dolt_status poisons the signature pass err := schema.MigrateUp(ctx, db) // unsafe dolt status table name "we;ird'name" // after: rename to a safe identifier via dolt, then migrate // dolt sql -q "RENAME TABLE `we;ird'name` TO weird_name" err = schema.MigrateUp(ctx, db)
Defensive patterns
Strategy: validation
Validate before calling
// Go: mirror the library's allowlist before creating tables in the beads DB
var safeTableRE = regexp.MustCompile(`^[A-Za-z_][A-Za-z0-9_]*$`)
func safeTableName(name string) bool { return safeTableRE.MatchString(name) } Type guard
// Go: extract the rejected name from the error message
func unsafeTableName(err error) (string, bool) {
const prefix = "unsafe dolt status table name "
if err == nil || !strings.Contains(err.Error(), prefix) {
return "", false
}
msg := err.Error()
i := strings.Index(msg, prefix)
rest := msg[i+len(prefix):]
if len(rest) >= 2 {
return strings.Trim(rest, "\""), true
}
return "", false
} Try / catch
err := schema.MigrateUp(ctx, db)
if err != nil {
if name, ok := unsafeTableName(err); ok {
// rename/drop `name` via dolt, then retry
return fmt.Errorf("fix table %q (rename to [A-Za-z0-9_]) and retry", name)
}
return err
} Prevention
- Only create tables in the beads database with plain identifier names (letters, digits, underscores)
- Never hand-edit dolt_status or the Dolt working set
- Run `dolt status` after using external tools against the DB to catch oddly named tables early
- Keep beads and the Dolt engine version-aligned so status-name formatting matches the allowlist regex
When it happens
Trigger: Any code path fingerprinting dirty tables (dirtyTableSignatures / changedDirtyTableSignatures during MigrateUp) encounters a table name in dolt_status that fails the safe-name regex — e.g. names with quotes, semicolons, backslashes, or other characters outside the allowlist pattern.
Common situations: A table created by hand or by another tool with exotic characters in its name inside the .beads Dolt database; a corrupted or tampered dolt_status; a Dolt version producing status entries with quoted/backticked name formatting that beads' regex does not accept.
Related errors
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/3492a08625e66e15.
Report an issue: GitHub.