{"record":{"id":"d27eab10ba08697b","repo":"gastownhall/beads","slug":"key-cannot-start-with-q-reserved-for-persistent","errorCode":null,"errorMessage":"key cannot start with %q (reserved for persistent memories; use 'bd remember' / 'bd forget')","messagePattern":"key cannot start with %q \\(reserved for persistent memories; use 'bd remember' / 'bd forget'\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/kv.go","lineNumber":38,"sourceCode":"func validateKVKey(key string) error {\n\tif key == \"\" {\n\t\treturn fmt.Errorf(\"key cannot be empty\")\n\t}\n\tif strings.TrimSpace(key) == \"\" {\n\t\treturn fmt.Errorf(\"key cannot be only whitespace\")\n\t}\n\t// Prevent keys that would create nested kv.kv.* prefixes\n\tif strings.HasPrefix(key, kvPrefix) {\n\t\treturn fmt.Errorf(\"key cannot start with 'kv.' (would create nested prefix)\")\n\t}\n\t// Reserve the persistent-memory namespace: a generic memory.* key would\n\t// store to kv.memory.*, indistinguishable from a `bd remember` memory, and\n\t// the merge resolver auto-resolves kv.memory.* conflicts with --theirs\n\t// (GH#2474). Without this guard a user's deliberate kv value could be\n\t// silently overridden by a remote on pull. Keep the namespace owned by\n\t// bd remember / bd forget.\n\tif strings.HasPrefix(key, kvkeys.MemoryPrefix) {\n\t\treturn fmt.Errorf(\"key cannot start with %q (reserved for persistent memories; use 'bd remember' / 'bd forget')\", kvkeys.MemoryPrefix)\n\t}\n\t// Prevent keys that look like internal config\n\tif strings.HasPrefix(key, \"sync.\") || strings.HasPrefix(key, \"conflict.\") ||\n\t\tstrings.HasPrefix(key, \"federation.\") || strings.HasPrefix(key, \"jira.\") ||\n\t\tstrings.HasPrefix(key, \"linear.\") || strings.HasPrefix(key, \"export.\") ||\n\t\tstrings.HasPrefix(key, \"import.\") {\n\t\treturn fmt.Errorf(\"key cannot start with reserved prefix %q\", strings.Split(key, \".\")[0]+\".\")\n\t}\n\treturn nil\n}\n\n// printKVSetResult renders the `bd kv set` success output. Shared by the\n// classic and proxied-server paths so the output shape cannot drift.\nfunc printKVSetResult(key, value string) error {\n\tif jsonOutput {\n\t\treturn outputJSON(map[string]string{\n\t\t\t\"key\":   key,\n\t\t\t\"value\": value,","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/kv.go#L20-L56","documentation":"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.","triggerScenarios":"Running `bd kv set memory.note \"...\"` or any key beginning with `memory.` through the kv set path.","commonSituations":"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.","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."],"exampleFix":"// before\nbd kv set memory.preferred-editor \"vim\"   // rejected\n// after\nbd kv set prefs.preferred-editor \"vim\"","handlingStrategy":"validation","validationCode":"case \"$KEY\" in memory.*) echo \"reserved: use bd remember instead\" >&2; exit 1;; esac\nbd kv set \"$KEY\" \"$VALUE\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["cli","validation","kv-store","reserved-namespace"],"backgroundTag":"reserved-namespace-conflict","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}