{"record":{"id":"dad2016b7f6451fc","repo":"headroomlabs-ai/headroom","slug":"windows-environment-mutation-is-missing-a-variable","errorCode":null,"errorMessage":"Windows environment mutation is missing a variable name","messagePattern":"Windows environment mutation is missing a variable name","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"headroom/install/providers.py","lineNumber":132,"sourceCode":"                target=\"env\",\n                kind=\"windows-env\",\n                data={\n                    \"name\": name,\n                    \"scope\": scope_name,\n                    \"previous\": None if previous == \"__HEADROOM_UNSET__\" else previous,\n                },\n            )\n        )\n    return mutations\n\n\ndef _remove_windows_env_scope(mutations: list[ManagedMutation]) -> None:\n    for mutation in mutations:\n        if mutation.kind != \"windows-env\":\n            continue\n        name = mutation.data.get(\"name\")\n        if not isinstance(name, str):\n            raise ValueError(\"Windows environment mutation is missing a variable name\")\n        scope_name = mutation.data.get(\"scope\", \"User\")\n        if not isinstance(scope_name, str):\n            raise ValueError(\"Windows environment mutation is missing a valid scope\")\n        previous = mutation.data.get(\"previous\")\n        if previous is None:\n            value_literal = \"$null\"\n        else:\n            value_literal = _powershell_literal(previous)\n        command = [\n            \"powershell\",\n            \"-NoProfile\",\n            \"-Command\",\n            f\"[Environment]::SetEnvironmentVariable({_powershell_literal(name)},{value_literal},{_powershell_literal(scope_name)})\",\n        ]\n        subprocess.run(command, check=True)\n\n\ndef apply_mutations(manifest: DeploymentManifest) -> list[ManagedMutation]:","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/headroomlabs-ai/headroom/blob/322425c43bffde1ed0b64fecf3cf5951565dd82b/headroom/install/providers.py#L114-L150","documentation":"Raised during uninstall/rollback in _remove_windows_env_scope when a persisted 'windows-env' ManagedMutation record lacks a valid 'name' string in its data dict. The mutation log is the record of what the installer changed (previous env var values) so it can be reverted; a record without a variable name cannot be reverted, so the loop aborts. This is internal-state corruption, almost always caused by an older manifest schema, a hand-edited manifest.json, or a bug that wrote incomplete mutation records.","triggerScenarios":"Running uninstall/rollback of a headroom deployment whose <deployment-root>/<profile>/manifest.json contains a windows-env mutation with name missing, null, or non-string (e.g. {}). Also when a new field was introduced and old manifests predate it.","commonSituations":"Upgrading headroom across schema changes; users hand-editing manifests to 'clean up'; partial writes if the process died mid-install; third-party tooling rewriting JSON and dropping empty-looking keys.","solutions":["Open the profile's manifest.json (path is in the error context / deployment root) and find the windows-env mutation; add the correct \"name\": \"<VAR>\" field.","If the variable name is unrecoverable, delete that single mutation entry and revert the remaining ones — then manually run [Environment]::SetEnvironmentVariable('<VAR>',$null,'User') for the known variable.","Regenerate state: fully uninstall via --force/cleanup if available, then reinstall to rebuild a valid manifest.","Report the schema gap if it reproduces on a fresh install — that indicates a writer bug, not corruption."],"exampleFix":"// before (manifest.json, corrupt entry)\n{\"kind\": \"windows-env\", \"data\": {\"scope\": \"User\", \"previous\": \"x\"}}\n\n// after\n{\"kind\": \"windows-env\", \"data\": {\"name\": \"HEADROOM_API_KEY\", \"scope\": \"User\", \"previous\": \"x\"}}","handlingStrategy":"validation","validationCode":"from headroom.install.providers import _remove_windows_env_scope  # if public elsewhere, prefer that API\n\nfor m in manifest.mutations:\n    if m.kind == \"windows-env\" and not isinstance(m.data.get(\"name\"), str):\n        raise SystemExit(f\"corrupt windows-env mutation (no name): {m.data!r} — fix manifest before uninstall\")","typeGuard":"def is_valid_windows_env_mutation(mutation) -> bool:\n    return (\n        mutation.kind == \"windows-env\"\n        and isinstance(mutation.data.get(\"name\"), str)\n        and isinstance(mutation.data.get(\"scope\", \"User\"), str)\n    )","tryCatchPattern":"try:\n    uninstall(profile)\nexcept ValueError as e:\n    if \"missing a variable name\" in str(e):\n        logger.error(\"manifest has incomplete windows-env records; edit %s and rerun\", manifest_path)\n        sys.exit(3)\n    raise","preventionTips":["Never hand-edit manifest.json without validating each mutation has name/scope/previous.","Avoid killing the process mid-install — partial writes are the usual corruption source.","Back up the profile directory before uninstall/upgrade on Windows."],"tags":["windows","manifest","rollback","corruption","internal-state"],"backgroundTag":null,"analyzedSha":"322425c43bffde1ed0b64fecf3cf5951565dd82b","analyzedAt":"2026-08-15T01:03:05.481Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}