gastownhall/beads · error
invalid key %q: expected storage-class.<issue-type> (e.g. st
Error message
invalid key %q: expected storage-class.<issue-type> (e.g. storage-class.event)
What it means
Set-time validation for storage-class config keys: the key must be `storage-class.<issue-type>` with exactly one dot and a non-empty suffix naming a canonical issue type. Anything else (empty suffix, extra dots like `storage-class.a.b`) is rejected when the config value is being set, per Protocol v0.1 C-OQ1.
Source
Thrown at cmd/bd/config.go:986
// they are derived from the tracker registry at runtime via
// allRecognizedConfigPrefixes, so the recognizer cannot drift out of sync when
// a new tracker is added (GH#4427).
var recognizedConfigPrefixes = []string{
"export.", "import.", "dolt.", "custom.",
"status.", "types.", "doctor.suppress.", "routing.", "sync.", "git.",
"directory.", "repos.", "external_projects.", "validation.",
"lint.", "hierarchy.", "ai.", "backup.", "federation.", "metrics.",
"agent.", "claim.", "storage-class.",
}
// validateStorageClassConfig validates a storage-class.<type> per-type
// default at config-set time (Protocol v0.1 C-OQ1: values are validated when
// set, not discovered broken at create time). The key suffix must name an
// issue type and the value must be a storage class.
func validateStorageClassConfig(key, value string) error {
suffix := strings.TrimPrefix(key, "storage-class.")
if suffix == "" || strings.Contains(suffix, ".") {
return fmt.Errorf("invalid key %q: expected storage-class.<issue-type> (e.g. storage-class.event)", key)
}
// The key suffix must be a canonical, known issue type: create-time lookup
// keys on the Normalize()d type (resolveStorageClass), so an alias like
// storage-class.feat or a typo like storage-class.taks would pass set-time
// validation and then silently never match — the C-OQ1 failure mode this
// validator exists to prevent.
issueType := types.IssueType(suffix)
if canonical := issueType.Normalize(); canonical != issueType {
return fmt.Errorf("invalid key %q: %q is an alias of %q, and create-time lookup uses the canonical type; set storage-class.%s instead", key, suffix, canonical, canonical)
}
if !issueType.IsValidWithCustom(loadEmbeddedCustomTypes()) {
return fmt.Errorf("invalid key %q: unknown issue type %q (use a built-in type, or add it to types.custom first)", key, suffix)
}
if _, err := types.ParseStorageClass(value); err != nil {
return err
}
return nil
}View on GitHub (pinned to 71377f2769)
Solutions
- Use the form storage-class.<issue-type>, e.g. `bd config set storage-class.event ephemeral`
- Remove any extra dot-separated segments from the key
- Confirm the issue-type suffix is canonical (not an alias like 'feat') — a later check also rejects aliases/typos
- Run `bd config list` to see existing valid keys as examples
Example fix
// before bd config set storage-class.bug.extra ephemeral // after bd config set storage-class.bug ephemeral
Defensive patterns
Strategy: validation
Validate before calling
# validate key shape before set case "$KEY" in storage-class.[a-z]*) : ;; *) echo "invalid: use storage-class.<issue-type>"; exit 1 ;; esac
Prevention
- Use canonical issue-type names (bug, feature, task, epic, chore), not aliases
- Never add extra dot segments to storage-class keys
- Script config sets with a fixed key template
- Check existing keys with bd config list as a shape reference
When it happens
Trigger: Running `bd config set storage-class.<something> <value>` where the suffix is empty (`storage-class.`) or contains another dot — e.g. `storage-class.bug.extra` or a bare `storage-class.` key.
Common situations: Typo with a trailing dot, nesting keys by habit (`storage-class.chore.subtype`), or scripting config sets with a malformed key template.
Related errors
- config storage-class.%s: %w
- invalid storage class %q (must be %s)
- server: NewDoltServer: doltBinExec is required
- server: NewDoltServer: rootDir is required
- server: NewDoltServer: configPath is required
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/c57f6e61e2738189.
Report an issue: GitHub.