{"record":{"id":"5c6c3105c79fa494","repo":"gastownhall/beads","slug":"key-cannot-be-empty","errorCode":null,"errorMessage":"key cannot be empty","messagePattern":"key cannot be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/kv.go","lineNumber":22,"sourceCode":"\t\"fmt\"\n\t\"os\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"github.com/spf13/cobra\"\n\n\t\"github.com/steveyegge/beads/internal/metrics\"\n\t\"github.com/steveyegge/beads/internal/storage/kvkeys\"\n)\n\n// kvPrefix is prepended to all user keys to separate them from internal config\nconst kvPrefix = kvkeys.Prefix\n\n// validateKVKey checks if a key is valid for the KV store.\n// Returns an error if the key is invalid.\nfunc 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","sourceCodeStart":4,"sourceCodeEnd":40,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/kv.go#L4-L40","documentation":"`bd kv set` validates every key through validateKVKey before writing to the KV store. An empty key gives the store nothing to address, so the CLI rejects it up front with this message instead of writing an unidentifiable record. It is the first of several guard clauses in the same validator.","triggerScenarios":"Running `bd kv set \"\" <value>` or calling validateKVKey(\"\") via the kv set/kv get code paths with an empty string key, e.g. from a script whose key variable is unset.","commonSituations":"Shell scripts where a variable holding the key name is empty/unset (`bd kv set \"$KEY\" \"$VAL\"` with KEY undefined); JSON/YAML templating that drops the key field.","solutions":["Re-run with a non-empty key: bd kv set <key> <value>.","Check the variable or template that produced the key; ensure it is populated before invoking bd.","Use `bd kv set` interactively first to confirm the key name you intend."],"exampleFix":"// before\nKEY=\"\"; bd kv set \"$KEY\" \"v\"\n// after\nKEY=\"my-setting\"; bd kv set \"$KEY\" \"v\"","handlingStrategy":"validation","validationCode":"if [ -z \"$KEY\" ]; then echo \"key must be non-empty\" >&2; exit 1; fi\nbd kv set \"$KEY\" \"$VALUE\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Default key variables in scripts (KEY=${KEY:-default-key}).","Assert key non-empty in wrappers before invoking bd kv.","Avoid interpolating keys from sources that may yield empty strings."],"tags":["cli","validation","kv-store"],"backgroundTag":"invalid-input-key","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}