gastownhall/beads · error
config storage-class.%s: %w
Error message
config storage-class.%s: %w
What it means
resolveStorageClass validates the storage-class value after deciding its source: an explicit --storage-class flag failure is returned bare (a usage error), but when the value came from per-type config (storage-class.<type>) and ParseStorageClass rejects it, the error is wrapped with the config key. This makes a bad config value identifiable as a configuration bug rather than a command-line mistake, and it fails loudly per Protocol v0.1 C1.3.
Source
Thrown at cmd/bd/create.go:731
// The parsed class is returned verbatim, including versioned. The caller must
// normalize versioned to the unset marker (the marker is omitted when
// versioned, C2.4) only AFTER plane-conflict validation, so an explicit durable
// request paired with a wisp-plane flag is rejected rather than silently erased
// into an effective-ephemeral row. Values are validated wherever they came
// from: a bad flag is a usage error, a bad config value is a config bug and
// fails just as loudly.
func resolveStorageClass(explicit string, issueType types.IssueType) (types.StorageClass, error) {
raw := explicit
if raw == "" {
raw = config.GetString("storage-class." + string(issueType))
if raw == "" {
return "", nil
}
}
class, err := types.ParseStorageClass(raw)
if err != nil {
if explicit == "" {
return "", fmt.Errorf("config storage-class.%s: %w", issueType, err)
}
return "", err
}
return class, nil
}
// reconcileStorageClassPlane applies flag-over-config precedence between a
// resolved storage class and the effective wisp plane (Protocol v0.1 §C1.3).
// A wisp-plane record is ephemeral by construction, so a durable class
// (versioned/unversioned) cannot ride on it. explicit reports whether the class
// came from an explicit flag/field rather than a per-type config default:
// - explicit durable class + wisp plane -> conflict=true; the caller rejects
// it so the durable intent is preserved rather than silently collapsed into
// an effective-ephemeral record;
// - config-derived durable class + wisp plane -> cleared, yielding to the
// explicit --ephemeral/--no-history plane.
//
// versioned normalizes to the unset marker (C2.4) only after the check, so theView on GitHub (pinned to 71377f2769)
Solutions
- Fix the config value for storage-class.<type> to a valid storage class (e.g. versioned/unversioned/ephemeral as accepted by types.ParseStorageClass)
- Run with an explicit --storage-class <valid> flag to override the bad config and unblock the create
- Print the effective config (`bd config` / config get storage-class.<type>) to confirm which key/value is being read
- Align with your team's config template and bd version — older or newer versions may accept different tokens
Example fix
# before (config) storage-class.bug: durable-ish # after storage-class.bug: versioned
Defensive patterns
Strategy: validation
Validate before calling
// Validate the config value before running bd create
raw := config.GetString("storage-class." + issueType)
if raw != "" {
if _, err := types.ParseStorageClass(raw); err != nil {
return fmt.Errorf("storage-class.%s is invalid: %w", issueType, err)
}
} Try / catch
sc, err := resolveStorageClass(explicit, issueType)
if err != nil {
if strings.HasPrefix(err.Error(), "config storage-class.") {
// bad config value: fix config, not the CLI flags
}
return err // bare error means bad --storage-class flag (usage error)
} Prevention
- Validate storage-class.<type> entries with types.ParseStorageClass at config-load time
- Only set the config key with tokens accepted by your bd version (check --help / docs)
- Prefer explicit --storage-class when scripting, so config drift can't break creates
- Keep team config templates versioned with the bd version that accepts their values
When it happens
Trigger: Creating an issue without --storage-class while config key storage-class.<issueType> (e.g. storage-class.bug in beads config or a config file) holds a value types.ParseStorageClass doesn't accept — misspelled class names, wrong case, or an unsupported token.
Common situations: Hand-edited config files with `storage-class.bug: durable-ish`; copied configs from docs of a different version; typos like `vesioned` instead of `versioned`; config applied to a type whose key was spelled wrong.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- invalid key %q: expected storage-class.<issue-type> (e.g. st
- 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/846db9e008b04fb8.
Report an issue: GitHub.