gastownhall/beads · error

key cannot start with reserved prefix %q

Error message

key cannot start with reserved prefix %q

What it means

Several key prefixes (sync., conflict., federation., jira., linear., export., import.) are reserved for internal bd configuration. A user key with one of these prefixes could collide with internal state, so validateKVKey rejects it and reports the offending prefix.

Source

Thrown at cmd/bd/kv.go:45

	// 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,
		})
	}
	fmt.Printf("Set %s = %s\n", key, value)
	return nil
}

// printKVGetResult renders the `bd kv get` output (including the not-found

View on GitHub (pinned to 71377f2769)

Solutions

  1. Choose a non-reserved key, e.g. prefix your own keys with something like `user.` or `custom.`.
  2. If you need to change internal behavior, use the corresponding bd command/flag rather than writing config keys directly.
  3. Inspect the validator in cmd/bd/kv.go for the full list of reserved prefixes.

Example fix

// before
bd kv set export.format json   // rejected
// after
bd kv set user.export-format json
Defensive patterns

Strategy: validation

Validate before calling

for p in sync. conflict. federation. jira. linear. export. import.; do
  case "$KEY" in "$p"*) echo "reserved prefix: $p" >&2; exit 1;; esac
done
bd kv set "$KEY" "$VALUE"

Prevention

When it happens

Trigger: Running `bd kv set sync.mykey ...`, `bd kv set export.flag ...`, or any key whose first dot-delimited segment matches a reserved prefix.

Common situations: Integration scripts mirroring internal config keys; users poking at internal settings they saw in the database or docs.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/12dba144fa0b3589. Report an issue: GitHub.