{"record":{"id":"6d5374f740e21659","repo":"headroomlabs-ai/headroom","slug":"windows-environment-mutation-is-missing-a-valid-sc","errorCode":null,"errorMessage":"Windows environment mutation is missing a valid scope","messagePattern":"Windows environment mutation is missing a valid scope","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"headroom/install/providers.py","lineNumber":135,"sourceCode":"                    \"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]:\n    \"\"\"Apply provider/user/system configuration for a deployment.\"\"\"\n\n    mutations: list[ManagedMutation] = []","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/headroomlabs-ai/headroom/blob/322425c43bffde1ed0b64fecf3cf5951565dd82b/headroom/install/providers.py#L117-L153","documentation":"Raised in _remove_windows_env_scope when a windows-env mutation's 'scope' field is present but not a string (it defaults to 'User' when absent, so this fires only on explicitly wrong types like scope: 1 or scope: null-that-was-loaded-as-non-str). The scope is passed to PowerShell's [Environment]::SetEnvironmentVariable as the third argument and must be the literal 'User', 'Machine', or 'Process'; a non-string cannot be safely interpolated, so rollback aborts.","triggerScenarios":"A manifest.json hand-edited or emitted by a buggy version where \"scope\" is a number/boolean/list; e.g. {\"scope\": 1} or {\"scope\": [\"User\"]}. Distinct from error 152: the name validated fine, only the scope is malformed.","commonSituations":"Schema drift between headroom versions (scope introduced later); JSON produced by scripts that coerce values; manual edits attempting to switch User->Machine scope incorrectly.","solutions":["Edit the mutation in manifest.json so \"scope\" is one of the strings \"User\", \"Machine\", or \"Process\" (matching how the value was originally set).","If unsure of the original scope, check what the install step used (installers almost always use 'User' on Windows for per-user installs).","Remove the malformed mutation entry and revert the variable manually in PowerShell.","Reinstall cleanly to regenerate the manifest if multiple entries are damaged."],"exampleFix":"// before\n{\"kind\": \"windows-env\", \"data\": {\"name\": \"HEADROOM_HOME\", \"scope\": 1, \"previous\": null}}\n\n// after\n{\"kind\": \"windows-env\", \"data\": {\"name\": \"HEADROOM_HOME\", \"scope\": \"User\", \"previous\": null}}","handlingStrategy":"validation","validationCode":"VALID_SCOPES = {\"User\", \"Machine\", \"Process\"}\n\nfor m in manifest.mutations:\n    if m.kind == \"windows-env\":\n        scope = m.data.get(\"scope\", \"User\")\n        assert isinstance(scope, str) and scope in VALID_SCOPES, f\"bad scope {scope!r} in {m.data!r}\"","typeGuard":"def has_valid_windows_scope(mutation) -> bool:\n    scope = mutation.data.get(\"scope\", \"User\") if mutation.kind == \"windows-env\" else None\n    return isinstance(scope, str) and scope in {\"User\", \"Machine\", \"Process\"}","tryCatchPattern":"try:\n    uninstall(profile)\nexcept ValueError as e:\n    if \"missing a valid scope\" in str(e):\n        fix_scope_in_manifest(manifest_path)  # set \"scope\": \"User\"\n        uninstall(profile)\n    else:\n        raise","preventionTips":["Keep \"scope\" as a JSON string ('User'/'Machine'/'Process') — never numbers or arrays.","Validate the whole manifest with a small schema check after any manual edit.","Upgrade headroom and manifests together to avoid schema drift between versions."],"tags":["windows","manifest","rollback","validation","schema"],"backgroundTag":null,"analyzedSha":"322425c43bffde1ed0b64fecf3cf5951565dd82b","analyzedAt":"2026-08-15T01:03:05.481Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}