2025, Oct 06 15:00

Fixing the 'frozen os in getitem' Error in Python and Safely Passing API Secrets on Windows

Learn why assigning a string to os.environ triggers 'frozen os in getitem' in Python, and how to pass API keys safely via .env or argparse on Windows.

Fixing “frozen os in getitem” in Python: when os.environ gets clobbered and how to pass secrets cleanly on Windows

Running a script that reads an API key from the environment and seeing the run crash with an error pointing at the key name is frustrating, especially if you tried to set the value at runtime on Windows. The root cause in this scenario is simpler than it looks: the code accidentally overwrites os.environ, so any subsequent attempt to read an environment variable fails.

The broken snippet

import requests
import json
import os
os.environ = "api.alpha.dev"
req_headers = {"Accept": "application/json", "Authorization": f"Bearer {os.environ['API_TOKEN']}"}
# params = {}
# ...rest of the script

With code like that, reading the value for the API key triggers a traceback that highlights the variable access. The behavior matches the description often summarized as:

you are trying to access an environment variable that is not currently set within the environment where your python script is running

The confusion comes from the fact that the value seemed to be provided at runtime, yet the script still cannot read it.

What’s actually going on

os.environ is a special mapping that exposes the process environment. Assigning a plain string to it wipes out that mapping entirely. After that assignment, any lookup like os.environ["API_TOKEN"] will fail because os.environ is no longer a dictionary-like object. Removing the assignment is the first and essential fix.

The minimal fix

import requests
import os
api_headers = {"Accept": "application/json", "Authorization": f"Bearer {os.environ['API_TOKEN']}"}
# continue with your logic

Once os.environ remains intact, you can choose how to supply the API key without hardcoding it. Two practical options are using a .env file during development or passing the value via command-line arguments.

Option 1: load from a .env file with python-dotenv

Install the helper package and keep secrets out of the codebase while still making them easy to provide in development.

pip install python-dotenv
# or
uv add python-dotenv

Create a .env file in the project directory and add your key:

API_TOKEN=abcd1234

Load it at startup and read the value from the environment:

from dotenv import load_dotenv
import os
load_dotenv()
headers_cfg = {"Authorization": f"Bearer {os.environ['API_TOKEN']}"}

This keeps the token out of source files and avoids hardcoding.

Option 2: pass values explicitly via command-line arguments

If you prefer to hand the API key and base URL directly at run time, use argparse to define a simple CLI. This works cleanly on Windows.

# client.py
import argparse
import requests
def run():
    parser = argparse.ArgumentParser(description="Run API client with key")
    parser.add_argument("--API_TOKEN", required=True, help="Your API key")
    parser.add_argument("--BASE_URL", required=False, default="https://website.abc.com",
                        help="Base URL of the API")
    opts = parser.parse_args()
    send_headers = {
        "Accept": "application/json",
        "Authorization": f"Bearer {opts.API_TOKEN}"
    }
    resp = requests.get(opts.BASE_URL, headers=send_headers)
    print("Status:", resp.status_code)
if __name__ == "__main__":
    run()

Run it like this:

python client.py --API_TOKEN abcd1234 --BASE_URL https://example.com/

Why this matters

Accidentally overwriting os.environ breaks every environment-based configuration lookup and leads to opaque errors that look like deployment or shell issues. Keeping configuration external to code—either in a .env file during development or through explicit CLI parameters—prevents hardcoding and keeps the behavior predictable across runs and machines.

Takeaways

Do not assign to os.environ; treat it as the read/write mapping it is. If you want to read a value from the environment, leave os.environ alone and fetch the key. For local development, load values from a .env file with python-dotenv. If you need to pass values at execution time on Windows, define proper flags with argparse and supply them on the command line. This small change removes the source of the error and makes your configuration flow clear and reliable.

The article is based on a question from StackOverflow by ithoughtso and an answer by Ajeet Verma.