gastownhall/beads · error
key cannot start with %q (reserved for persistent memories;
Error message
key cannot start with %q (reserved for persistent memories; use 'bd remember' / 'bd forget')
What it means
The `memory.*` namespace is reserved for persistent memories created via `bd remember`/`bd forget`. Allowing generic `memory.*` KV keys would collide with memories stored at kv.memory.*, which the merge resolver auto-resolves with --theirs (GH#2474), silently overwriting the user's value on pull. validateKVKey rejects keys starting with the memory prefix to keep that namespace owned by remember/forget.
Source
Thrown at cmd/bd/kv.go:38
func validateKVKey(key string) error {
if key == "" {
return fmt.Errorf("key cannot be empty")
}
if strings.TrimSpace(key) == "" {
return fmt.Errorf("key cannot be only whitespace")
}
// Prevent keys that would create nested kv.kv.* prefixes
if strings.HasPrefix(key, kvPrefix) {
return fmt.Errorf("key cannot start with 'kv.' (would create nested prefix)")
}
// Reserve the persistent-memory namespace: a generic memory.* key would
// store to kv.memory.*, indistinguishable from a `bd remember` memory, and
// the merge resolver auto-resolves kv.memory.* conflicts with --theirs
// (GH#2474). Without this guard a user's deliberate kv value could be
// silently overridden by a remote on pull. Keep the namespace owned by
// bd remember / bd forget.
if strings.HasPrefix(key, kvkeys.MemoryPrefix) {
return fmt.Errorf("key cannot start with %q (reserved for persistent memories; use 'bd remember' / 'bd forget')", kvkeys.MemoryPrefix)
}
// Prevent keys that look like internal config
if strings.HasPrefix(key, "sync.") || strings.HasPrefix(key, "conflict.") ||
strings.HasPrefix(key, "federation.") || strings.HasPrefix(key, "jira.") ||
strings.HasPrefix(key, "linear.") || strings.HasPrefix(key, "export.") ||
strings.HasPrefix(key, "import.") {
return fmt.Errorf("key cannot start with reserved prefix %q", strings.Split(key, ".")[0]+".")
}
return nil
}
// printKVSetResult renders the `bd kv set` success output. Shared by the
// classic and proxied-server paths so the output shape cannot drift.
func printKVSetResult(key, value string) error {
if jsonOutput {
return outputJSON(map[string]string{
"key": key,
"value": value,View on GitHub (pinned to 71377f2769)
Solutions
- Use `bd remember <text>` to store a memory instead of kv set memory.*.
- Rename the key to avoid the reserved prefix, e.g. bd kv set notes.myitem ...
- Check `bd forget --help` / memory docs to understand the reserved namespace.
Example fix
// before bd kv set memory.preferred-editor "vim" // rejected // after bd kv set prefs.preferred-editor "vim"
Defensive patterns
Strategy: validation
Validate before calling
case "$KEY" in memory.*) echo "reserved: use bd remember instead" >&2; exit 1;; esac bd kv set "$KEY" "$VALUE"
Prevention
- Use `bd remember`/`bd forget` for anything memory-like.
- Prefix personal kv keys distinctly (e.g. user., custom.).
- Keep a list of reserved prefixes (kv., memory., sync., etc.) in team tooling.
When it happens
Trigger: Running `bd kv set memory.note "..."` or any key beginning with `memory.` through the kv set path.
Common situations: Users treating kv as a generic store and choosing `memory.x` as a natural key name; scripts syncing notes into kv that conflict with the memories feature.
Related errors
- key cannot start with reserved prefix %q
- key cannot be empty
- key cannot be only whitespace
- key cannot start with 'kv.' (would create nested prefix)
- got %d close reasons for %d issue IDs; provide exactly one s
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/d27eab10ba08697b.
Report an issue: GitHub.