harry0703/MoneyPrinterTurbo · error · HttpException

invalid token: {request_url}, {user_agent}

Error message

invalid token: {request_url}, {user_agent}

What it means

Raised by verify_token in app/controllers/base.py when the x-api-key header does not match the api_key configured in config.app. Every authenticated v1 endpoint funnels through this check, so any mismatched or missing key yields a 401 before business logic runs. The message intentionally echoes the request URL and User-Agent to help server operators correlate rejected calls in logs.

Source

Thrown at app/controllers/base.py:27

def get_task_id(request: Request):
    task_id = request.headers.get("x-task-id")
    if not task_id:
        task_id = uuid4()
    return str(task_id)


def get_api_key(request: Request):
    api_key = request.headers.get("x-api-key")
    return api_key


def verify_token(request: Request):
    token = get_api_key(request)
    if token != config.app.get("api_key", ""):
        request_id = get_task_id(request)
        request_url = request.url
        user_agent = request.headers.get("user-agent")
        raise HttpException(
            task_id=request_id,
            status_code=401,
            message=f"invalid token: {request_url}, {user_agent}",
        )

View on GitHub (pinned to 1f9f19c202)

Solutions

  1. Compare the exact value of the x-api-key header against config.app['api_key'] in the running process; fix the client or the config so they match.
  2. If the server has no api_key configured, set one in the app config and restart, then use it on the client.
  3. Check that no proxy/gateway strips the x-api-key header and that the header name is lowercase-safe in your HTTP client.
  4. Verify the key is sent as a raw header value without extra quotes, 'Bearer ' prefix, or trailing newline.

Example fix

# before
curl http://localhost:8080/api/v1/tasks -H "x-api-key: Bearer my-secret"

# after
curl http://localhost:8080/api/v1/tasks -H "x-api-key: my-secret"
Defensive patterns

Strategy: validation

Validate before calling

# client: fail fast on obviously missing/malformed key before any call
key = os.environ.get("APP_API_KEY", "")
if not key or key.strip() != key:
    raise RuntimeError("APP_API_KEY is missing or has surrounding whitespace")

Type guard

def is_valid_api_key_shape(key: str | None) -> bool:
    return isinstance(key, str) and 0 < len(key) == len(key.strip())

Try / catch

# server-side callers: treat 401 as terminal, not retryable
try:
    resp = client.get("/api/v1/tasks")
except HTTPError as e:
    if e.response.status_code == 401:
        raise RuntimeError("API key rejected; check x-api-key header vs server config") from e
    raise

Prevention

When it happens

Trigger: Calling any /api/v1 endpoint without the x-api-key header; sending a key that differs from config.app['api_key']; rotating the key on the server while clients still use the old one; whitespace/quoting issues when the key is passed via curl or a shell variable.

Common situations: Fresh deployments where api_key was never set in the config file (defaults to empty string, so any non-empty sent key fails); CI pipelines that inject the key incorrectly; key rotated between environments (dev vs prod); proxy or gateway stripping custom headers.

Understand the failure class

Related errors


AI-assisted analysis of harry0703/MoneyPrinterTurbo@1f9f19c202 (2026-08-14). Data as JSON: /api/errors/427357a8b5330d8a. Report an issue: GitHub.