The Token Was Valid. My Headless Agent 401'd Anyway.

I built two small tools to call Claude via code. One generates commit messages. The other updates profiles.

The code looked perfect. It grabbed an API key from the environment. It sent a raw HTTPS request to the Anthropic API. It parsed the JSON response.

It failed every time with a 401 error.

The problem was not the code. The problem was the authentication method.

I do not use a raw API key. I use Claude Code through a subscription. This uses OAuth through the Claude CLI. This is a different system than the one my script expected.

My environment had a stale or empty value under the API key variable. The script saw a value and thought it was valid. The request went out with the wrong type of credential.

The fix was simple. I stopped making direct API calls. Instead, I told my script to use the CLI that already has a valid session.

Old way: Use urllib to send a request with an API key.

New way: Use subprocess to run the "claude" command directly.

The CLI handles the session, the tokens, and the expiry for you.

This mistake is dangerous in headless environments. A human sees an error in a terminal. A cron job or a CI pipeline fails silently. You might not notice for days.

You will see this same pattern in other places:

  • A tool looks for a personal access token but the system uses OIDC.
  • A script reads AWS keys while the system uses an IAM role.

The token is present. The token is well-formed. It passes basic checks but uses the wrong mechanism.

Follow these rules to avoid this:

  • Ask how your environment authenticates interactively before writing code. Do not just follow the API documentation.
  • Do not trust os.environ. A present value might be stale or wrong.
  • If a CLI tool handles authentication for you, use it. Shell out to the CLI instead of rebuilding the auth logic yourself.
  • If you get a 401 error, check your credential path before you change your request code.

Source: https://dev.to/enjoy_kumawat/the-token-was-valid-my-headless-agent-401d-anyway-3bgl

Optional learning community: https://t.me/GyaanSetuAi