gastownhall/beads · error
invalid table name: %s
Error message
invalid table name: %s
What it means
validateTableName rejects names that do not match validTablePattern. Because table names are interpolated into backtick-quoted SQL statements, characters that could escape the quoting (backticks, quotes, special symbols) are forbidden. The offending name appears in the error message.
Source
Thrown at internal/storage/dolt/history.go:51
if len(name) > 64 {
return fmt.Errorf("database name too long")
}
if !validDatabasePattern.MatchString(name) {
return fmt.Errorf("invalid database name: %s", name)
}
return nil
}
// validateTableName checks if a table name is safe to use in queries
func validateTableName(table string) error {
if table == "" {
return fmt.Errorf("table name cannot be empty")
}
if len(table) > 64 {
return fmt.Errorf("table name too long")
}
if !validTablePattern.MatchString(table) {
return fmt.Errorf("invalid table name: %s", table)
}
return nil
}
// issueHistory represents an issue at a specific point in history
type issueHistory struct {
Issue *types.Issue
CommitHash string
Committer string
CommitDate time.Time
}
// getIssueHistory returns the complete history of an issue
func (s *DoltStore) getIssueHistory(ctx context.Context, issueID string) ([]*issueHistory, error) {
// Wrap in a subquery to avoid Dolt's max1Row optimization on PK lookup.
// dolt_history_* tables return multiple rows per PK (one per commit),
// but the query planner incorrectly assumes WHERE id=? returns one row.
rows, err := s.queryContext(ctx, `View on GitHub (pinned to 71377f2769)
Solutions
- Sanitize the table name to plain identifier characters (letters, digits, underscores) before passing it to any dolt query helper.
- Never accept raw user input as a table name; map user choices to a fixed allowlist of known table names.
- If the name comes from configuration, validate the config value at load time against the same pattern.
Example fix
// before
table := r.URL.Query().Get("table") // "issues; DROP TABLE x"
store.QueryHistory(ctx, id, table)
// after
var allowed = map[string]bool{"issues": true, "wisps": true}
table := r.URL.Query().Get("table")
if !allowed[table] { return fmt.Errorf("unknown table") }
store.QueryHistory(ctx, id, table) Defensive patterns
Strategy: validation
Validate before calling
var tablePattern = regexp.MustCompile(`^[A-Za-z0-9_]+$`)
func validTableName(t string) bool { return tablePattern.MatchString(t) }
if !validTableName(table) { return fmt.Errorf("table name %q contains invalid characters", table) } Prevention
- Never feed user input directly into table names; map user choices to an allowlist of known tables.
- Validate table names from config at load time with the same pattern the library uses.
- Keep table-name construction in one audited helper.
When it happens
Trigger: Passing a table name containing backticks, quotes, spaces, semicolons, slashes, or other non-identifier characters into a query path guarded by validateTableName.
Common situations: User-supplied table/filter input reaching an internal query; dynamically built table names from external config with path-like values ('org/repo'); injection attempts being safely rejected by this guard.
Related errors
- invalid database name: %s
- table name cannot be empty
- table name too long
- invalid --dolt-auto-commit=%q (valid: off, on, batch)
- remote target %s is non-empty but is neither a bare git repo
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/40ab3bebb8d971cd.
Report an issue: GitHub.