MemPalace/mempalace · error · WriteRoutingError

config write_routing must be an object

Error message

config write_routing must be an object

What it means

WriteRoutingError raised when the top-level 'write_routing' key in the MemPalace config file exists but is not a mapping (a JSON object / YAML dict). None is tolerated (treated as absent), but a string, list, or number fails the isinstance(routing_config, dict) check at mempalace/config.py:1018. The write-routing block must be an object because keys like 'default' are read from it.

Source

Thrown at mempalace/config.py:1018

        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"),
            ),
        ]

        if normalized_scope == "hooks":
            candidates.append(
                RoutingPolicyCandidate(
                    "MEMPALACE_HOOKS_DAEMON (legacy)",
                    os.environ.get("MEMPALACE_HOOKS_DAEMON"),
                    legacy_boolean=True,

View on GitHub (pinned to 06cb6987f0)

Solutions

  1. Make write_routing an object: {"default": "<policy>"} (or remove the key entirely to use defaults).
  2. Validate the config file loads as a mapping at that key: python -c "import json;c=json.load(open('mempalace.json'));assert isinstance(c.get('write_routing',{}),dict)".
  3. Re-run the write-routing resolution after fixing to confirm the error clears.

Example fix

# before (mempalace.json)
"write_routing": "direct"

# after
"write_routing": {"default": "direct"}
Defensive patterns

Strategy: validation

Validate before calling

import json

cfg = json.load(open("mempalace.json"))
wr = cfg.get("write_routing", {})
if wr is not None and not isinstance(wr, dict):
    raise SystemExit("write_routing must be an object, e.g. {\"default\": \"direct\"}")

Type guard

def is_write_routing_block(value: object) -> bool:
    return value is None or isinstance(value, dict)

Try / catch

try:
    policy = config.write_routing_policy("cli")
except WriteRoutingError as exc:
    print(f"config error: {exc}")  # point user at the file key; no retry

Prevention

When it happens

Trigger: Setting write_routing: "direct" (a bare string) in mempalace.json instead of {"default": "direct"}; writing write_routing: ["direct"] as a YAML list; a YAML dash or indentation mistake turning the object into a scalar; merging configs programmatically and clobbering the dict with a scalar.

Common situations: Hand-editing config files quickly and using shorthand syntax; converting config between JSON and YAML formats; copying a partial example from docs that shows only the value, not the object wrapper.

Related errors


AI-assisted analysis of MemPalace/mempalace@06cb6987f0 (2026-08-15). Data as JSON: /api/errors/7cfbf3fc169af620. Report an issue: GitHub.