MemPalace/mempalace · error · WriteRoutingError
write routing scope must be 'hooks' or 'cli'
Error message
write routing scope must be 'hooks' or 'cli'
What it means
WriteRoutingError raised in MempalaceConfig's write-routing resolution (mempalace/config.py:1011) when the scope argument passed to the policy resolver is not 'hooks' or 'cli' after strip+lower normalization. The scope selects which environment variable (MEMPALACE_HOOK_WRITE_ROUTING vs MEMPALACE_CLI_WRITE_ROUTING) anchors the candidate chain, so an unknown scope has no defined semantics and is rejected before any config is read.
Source
Thrown at mempalace/config.py:1011
2. global environment variable;
3. legacy hook environment variable;
4. scope-specific config value;
5. global config value;
6. legacy hook config value;
7. ``direct``.
This foundation does not change current hook or CLI behavior. The
policy-aware consumers are introduced by follow-up PRs.
"""
normalized_scope = str(scope).strip().lower()
env_names = {
"hooks": "MEMPALACE_HOOK_WRITE_ROUTING",
"cli": "MEMPALACE_CLI_WRITE_ROUTING",
}
if normalized_scope not in env_names:
raise WriteRoutingError("write routing scope must be 'hooks' or 'cli'")
routing_config = self._file_config.get("write_routing", {})
if routing_config is None:
routing_config = {}
if not isinstance(routing_config, dict):
raise WriteRoutingError("config write_routing must be an object")
candidates = [
RoutingPolicyCandidate(
env_names[normalized_scope],
os.environ.get(env_names[normalized_scope]),
),
RoutingPolicyCandidate(
"MEMPALACE_WRITE_ROUTING",
os.environ.get("MEMPALACE_WRITE_ROUTING"),
),
]View on GitHub (pinned to 06cb6987f0)
Solutions
- Pass exactly 'hooks' or 'cli' (case-insensitive; surrounding whitespace is tolerated) to the resolution method.
- If adding a genuinely new write path, extend the env_names mapping in config.py rather than passing an ad-hoc scope.
- Search your call sites for the scope value being interpolated (rg for the method name) and fix the producer of the bad value.
Example fix
# before
policy = config.write_routing_policy("mcp")
# after
policy = config.write_routing_policy("cli") Defensive patterns
Strategy: type-guard
Validate before calling
scope = scope.strip().lower()
assert scope in {"hooks", "cli"}, f"bad scope: {scope!r}" Type guard
from typing import Literal
WriteScope = Literal["hooks", "cli"]
def is_write_scope(value: object) -> bool:
return isinstance(value, str) and value.strip().lower() in {"hooks", "cli"} Try / catch
from mempalace.config import WriteRoutingError
try:
policy = config.write_routing_policy(scope)
except WriteRoutingError as exc:
# surface caller-facing config error; do not retry
raise Prevention
- Type scope parameters as Literal['hooks','cli'] so type checkers catch bad call sites.
- Never build the scope string from unvalidated user input.
- Keep a single constant per entry point instead of ad-hoc strings.
When it happens
Trigger: Calling the internal write-routing resolution method with scope="mcp", scope="hook" (singular), or scope="" ; passing a non-string scope like None or 1 that str()-ifies to something outside {hooks, cli}; a new call site added during development that uses an unsanitized scope string from user input.
Common situations: Extending MemPalace with a new entry point (e.g. an MCP tool path) and passing that label as the scope; refactoring that renames scope constants; dynamic scope built from a config key or CLI arg that is misspelled.
Related errors
- ChromaBackend has been closed
- milvus_consistency_level must be one of: {allowed}
- config write_routing must be an object
- config hooks must be an object
- {type(self).name} does not advertise supports_namespace_isol
AI-assisted analysis of MemPalace/mempalace@06cb6987f0 (2026-08-15).
Data as JSON: /api/errors/a33799672ee1f895.
Report an issue: GitHub.