{"record":{"id":"8c6a55c8ec33d998","repo":"headroomlabs-ai/headroom","slug":"self-config-env-var-does-not-match-config-payloa","errorCode":null,"errorMessage":"{self.config_env_var} does not match config_payload","messagePattern":"(.+?) does not match config_payload","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"headroom/testing/harness.py","lineNumber":398,"sourceCode":"    config_env_var: str = \"HEADROOM_PROXY_CONFIG_JSON\"\n\n    def to_dict(self) -> dict[str, Any]:\n        return {\n            \"command\": list(self.command),\n            \"env\": dict(self.env),\n            \"config_payload\": dict(self.config_payload),\n            \"config_env_var\": self.config_env_var,\n        }\n\n    def validate(self) -> None:\n        \"\"\"Fail if the environment does not round-trip the full config payload.\"\"\"\n\n        raw = self.env.get(self.config_env_var)\n        if raw is None:\n            raise ValueError(f\"deployment env missing {self.config_env_var}\")\n        parsed = json.loads(raw)\n        if parsed != self.config_payload:\n            raise ValueError(f\"{self.config_env_var} does not match config_payload\")\n\n\ndef _field_contract(\n    owner: Literal[\"headroom\", \"proxy\"], cls: type[Any]\n) -> tuple[FieldContract, ...]:\n    if not is_dataclass(cls):\n        raise TypeError(f\"{cls!r} must be a dataclass\")\n    out: list[FieldContract] = []\n    for field in cls.__dataclass_fields__.values():\n        default: Any = MISSING\n        if field.default is not MISSING:\n            default = field.default\n        elif field.default_factory is not MISSING:  # type: ignore[attr-defined]\n            default = \"<factory>\"\n        out.append(\n            FieldContract(\n                owner=owner,\n                name=field.name,","sourceCodeStart":380,"sourceCodeEnd":416,"githubUrl":"https://github.com/headroomlabs-ai/headroom/blob/322425c43bffde1ed0b64fecf3cf5951565dd82b/headroom/testing/harness.py#L380-L416","documentation":"ValueError raised by DeploymentSpec.validate() in headroom/testing/harness.py when the config env var IS present but its JSON content does not equal spec.config_payload (json.loads(raw) != config_payload). This catches drift between the payload the test believes it deployed and what the environment actually carries — e.g. an older serialization, partial update, or different key ordering is fine (dict equality) but different values/keys are not.","triggerScenarios":"Setting spec.env['HEADROOM_PROXY_CONFIG_JSON'] to a hand-written or stale JSON string instead of json.dumps(spec.config_payload); mutating spec.config_payload after injecting the env var; double-encoding (dumps of an already-JSON string).","commonSituations":"Tests that tweak config fields after building the deployment; fixtures caching serialized configs; copy-pasting an env var from a previous run's log.","solutions":["Regenerate the env var from the payload: spec.env[spec.config_env_var] = json.dumps(spec.config_payload).","If you must mutate config_payload, re-serialize immediately afterwards.","Prefer the harness's own builder (to_dict/from_dict) over hand-assembling the env var."],"exampleFix":"# before\nspec.config_payload['mode'] = 'cache'   # mutated after injection\nspec.validate()  # ValueError: does not match\n\n# after\nspec.config_payload['mode'] = 'cache'\nspec.env['HEADROOM_PROXY_CONFIG_JSON'] = json.dumps(spec.config_payload)\nspec.validate()","handlingStrategy":"validation","validationCode":"import json\n\ndef env_matches_payload(spec) -> bool:\n    raw = spec.env.get(spec.config_env_var)\n    if raw is None:\n        return False\n    try:\n        return json.loads(raw) == spec.config_payload\n    except json.JSONDecodeError:\n        return False","typeGuard":null,"tryCatchPattern":"try:\n    spec.validate()\nexcept ValueError as e:\n    if 'does not match' in str(e):\n        spec.env[spec.config_env_var] = json.dumps(spec.config_payload)\n        spec.validate()\n    else:\n        raise","preventionTips":["Single helper that always writes the env var from the payload — never edit one without the other.","Run validate() in test setup, not just teardown."],"tags":["testing","deployment","configuration","drift"],"backgroundTag":null,"analyzedSha":"322425c43bffde1ed0b64fecf3cf5951565dd82b","analyzedAt":"2026-08-15T01:03:05.481Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}