gastownhall/beads · critical
load %s: %w
Error message
load %s: %w
What it means
serveDatabaseSource refuses to continue when metadata.json (via configfile.Load) cannot be read or parsed. Per the comment, this is a hard error: the classification's default is an embedded refusal, so falling back would silently refuse a workspace whose backend nobody could read. The error names the actual config path plus the underlying cause.
Source
Thrown at cmd/bd/serve.go:561
// be handed to the Dolt provider and fail with a misleading Dolt error — or
// connect to a defaulted host and serve the wrong database.
//
// EMBEDDED DOLT IS PERMANENT, and this is the only place that refusal lives.
// Its commit protocol runs outside the SQL transaction on a separate
// connection, so the per-request atomicity this server's contract states would
// be a lie there. That is a property of the backend rather than of what has
// been built so far, which is also why no unit-of-work provider for it exists
// or will. Nothing downstream will catch a bypass: internal/httpapi cannot see
// the backend behind a role, and every store publishes every role accessor
// whatever it is. TestServeNamesOneDatabaseSourcePerServerItBuilds pins that
// the roles are only ever reached through here.
func serveDatabaseSource(beadsDir string) (serveDatabase, error) {
cfg, err := configfile.Load(beadsDir)
if err != nil {
// Never classify past an unreadable metadata.json. The classification's
// default is the embedded refusal, so falling back would refuse a
// workspace whose real backend nobody managed to read.
return serveDatabase{}, fmt.Errorf("load %s: %w", configfile.ConfigPath(beadsDir), err)
}
if backend := normalizeLoadedConfig(cfg).GetBackend(); backends.Registered(backend) {
return serveDatabase{source: serveSourceStore, backend: backend}, nil
}
if isEmbeddedMode() {
return serveDatabase{}, errServeEmbedded()
}
return serveDatabase{source: serveSourceProvider}, nil
}
// errServeReadonly refuses `bd --readonly serve`.
//
// AHEAD OF THE WORKSPACE, deliberately: every server this command builds
// publishes the same operation set, claim included, so the answer cannot depend
// on which database source the workspace resolves to. Putting it here is also
// what makes it one answer rather than two — the two sources degraded
// differently, and both silently.
//View on GitHub (pinned to 71377f2769)
Solutions
- Inspect the file named in the error (the metadata.json path) for valid JSON and fix it.
- Restore metadata.json from git or re-run `bd init`/backend setup to regenerate it.
- Fix file permissions for the serving user.
- Inspect the wrapped err via errors.Unwrap/errors.Is for the exact I/O or parse cause.
Example fix
// after failure, inspect and repair: python3 -m json.tool .beads/metadata.json # show parse error git checkout -- .beads/metadata.json # or fix manually, then retry bd serve
Defensive patterns
Strategy: try-catch
Validate before calling
if _, err := os.Stat(configfile.ConfigPath(beadsDir)); err != nil {
// metadata.json missing entirely — run bd init or backend setup
} Try / catch
db, err := serveDatabaseSource(beadsDir)
if err != nil {
// validate/repair the metadata.json named in the error; never assume embedded fallback
return err
} Prevention
- Never hand-edit metadata.json without validating JSON afterwards.
- Commit a valid metadata.json so clones start from a good state.
- Avoid killing bd mid-write; let writes complete.
- If the file is corrupt, restore from git or regenerate via bd init.
When it happens
Trigger: `bd serve` in a workspace where .beads/metadata.json is corrupt, malformed JSON, unreadable, or locked; ConfigPath(beadsDir) points at a file the process cannot read.
Common situations: Hand-edited metadata.json with invalid JSON; interrupted write left a truncated metadata.json; permission issues after cloning a repo as another user; concurrent writes corrupting the file.
Related errors
- load %s: %w (refusing to fall back to the embedded store)
- configured storage backend %q in metadata.json is not recogn
- not using Dolt backend (configured backend %q)
- no storage available
- --auth-token-file: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/07ade33263fa3b03.
Report an issue: GitHub.