{"record":{"id":"427357a8b5330d8a","repo":"harry0703/MoneyPrinterTurbo","slug":"invalid-token-request-url-user-agent","errorCode":null,"errorMessage":"invalid token: {request_url}, {user_agent}","messagePattern":"invalid token: (.+?), (.+?)","errorType":"http","errorClass":"HttpException","httpStatus":401,"severity":"error","filePath":"app/controllers/base.py","lineNumber":27,"sourceCode":"def get_task_id(request: Request):\n    task_id = request.headers.get(\"x-task-id\")\n    if not task_id:\n        task_id = uuid4()\n    return str(task_id)\n\n\ndef get_api_key(request: Request):\n    api_key = request.headers.get(\"x-api-key\")\n    return api_key\n\n\ndef verify_token(request: Request):\n    token = get_api_key(request)\n    if token != config.app.get(\"api_key\", \"\"):\n        request_id = get_task_id(request)\n        request_url = request.url\n        user_agent = request.headers.get(\"user-agent\")\n        raise HttpException(\n            task_id=request_id,\n            status_code=401,\n            message=f\"invalid token: {request_url}, {user_agent}\",\n        )\n","sourceCodeStart":9,"sourceCodeEnd":32,"githubUrl":"https://github.com/harry0703/MoneyPrinterTurbo/blob/1f9f19c2021a68d04df228f33e9099a0c947f6f8/app/controllers/base.py#L9-L32","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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.","If the server has no api_key configured, set one in the app config and restart, then use it on the client.","Check that no proxy/gateway strips the x-api-key header and that the header name is lowercase-safe in your HTTP client.","Verify the key is sent as a raw header value without extra quotes, 'Bearer ' prefix, or trailing newline."],"exampleFix":"# before\ncurl http://localhost:8080/api/v1/tasks -H \"x-api-key: Bearer my-secret\"\n\n# after\ncurl http://localhost:8080/api/v1/tasks -H \"x-api-key: my-secret\"","handlingStrategy":"validation","validationCode":"# client: fail fast on obviously missing/malformed key before any call\nkey = os.environ.get(\"APP_API_KEY\", \"\")\nif not key or key.strip() != key:\n    raise RuntimeError(\"APP_API_KEY is missing or has surrounding whitespace\")","typeGuard":"def is_valid_api_key_shape(key: str | None) -> bool:\n    return isinstance(key, str) and 0 < len(key) == len(key.strip())","tryCatchPattern":"# server-side callers: treat 401 as terminal, not retryable\ntry:\n    resp = client.get(\"/api/v1/tasks\")\nexcept HTTPError as e:\n    if e.response.status_code == 401:\n        raise RuntimeError(\"API key rejected; check x-api-key header vs server config\") from e\n    raise","preventionTips":["Load the API key from one shared source (env/secret manager) for both client and server.","Never send 'Bearer ' prefixes with x-api-key; the comparison is exact-string.","Add a startup smoke test that calls one authenticated endpoint and fails deployment on 401."],"tags":["auth","api-key","http-401","fastapi"],"backgroundTag":null,"analyzedSha":"1f9f19c2021a68d04df228f33e9099a0c947f6f8","analyzedAt":"2026-08-14T19:41:05.568Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}