{"record":{"id":"5d8fc9c067e7796e","repo":"Fosowl/agenticSeek","slug":"invalid-api-token","errorCode":null,"errorMessage":"Invalid API token","messagePattern":"Invalid API token","errorType":"http","errorClass":"HTTPException","httpStatus":401,"severity":"error","filePath":"sources/api_auth.py","lineNumber":28,"sourceCode":"import os\n\nfrom fastapi import Header, HTTPException\n\n\nasync def require_api_token(authorization: str | None = Header(default=None)) -> None:\n    expected_token = os.getenv(\"AGENTICSEEK_API_TOKEN\")\n    if not expected_token:\n        return\n\n    if not authorization or not authorization.startswith(\"Bearer \"):\n        raise HTTPException(\n            status_code=401,\n            detail=\"Missing or malformed Authorization header\",\n        )\n\n    provided_token = authorization[len(\"Bearer \"):]\n    if not hmac.compare_digest(provided_token, expected_token):\n        raise HTTPException(status_code=401, detail=\"Invalid API token\")\n","sourceCodeStart":10,"sourceCodeEnd":29,"githubUrl":"https://github.com/Fosowl/agenticSeek/blob/ae57a2357745a9706cb12d0fd76d954c84d166fa/sources/api_auth.py#L10-L29","documentation":"After validating the header format, require_api_token compares the provided Bearer token to AGENTICSEEK_API_TOKEN using hmac.compare_digest (constant-time). Any mismatch returns 401 with \"Invalid API token\". This means the header was well-formed but the credential value is wrong.","triggerScenarios":"Sending Authorization: Bearer <token> where token != os.getenv(\"AGENTICSEEK_API_TOKEN\") — wrong/stale token, whitespace or quoting around the value, trailing newline from a file-based secret, or client pointing at an environment with a different token.","commonSituations":"Client and server configured from different .env files; token rotated on the server but not the client; copying the token with surrounding quotes or a trailing \\n; extra spaces after \"Bearer \"; staging vs. production tokens mixed up.","solutions":["Regenerate/verify the token and set the exact same AGENTICSEEK_API_TOKEN value on the client.","Strip whitespace/newlines/quotes from the token value before sending (token.strip()).","Diff the server's env (`printenv AGENTICSEEK_API_TOKEN`) against what the client sends to confirm they match byte-for-byte.","If loading from a secret file, read with .read().strip() to avoid trailing newline mismatches."],"exampleFix":"// before\ntoken = open(\"token.txt\").read()  # may contain trailing \\n\nheaders = {\"Authorization\": f\"Bearer {token}\"}  # 401 Invalid API token\n// after\ntoken = open(\"token.txt\").read().strip()\nheaders = {\"Authorization\": f\"Bearer {token}\"}","handlingStrategy":"validation","validationCode":"import os\ndef get_bearer_header(env_var=\"AGENTICSEEK_API_TOKEN\") -> dict:\n    token = os.environ.get(env_var, \"\").strip().strip('\"')\n    if not token:\n        raise RuntimeError(f\"{env_var} not set on client\")\n    return {\"Authorization\": f\"Bearer {token}\"}","typeGuard":null,"tryCatchPattern":"try:\n    resp = requests.get(url, headers=headers)\n    resp.raise_for_status()\nexcept requests.HTTPError as e:\n    if e.response.status_code == 401 and \"Invalid API token\" in e.response.json().get(\"detail\", \"\"):\n        token = input(\"Token rejected; re-enter AGENTICSEEK_API_TOKEN value: \").strip()\n        headers[\"Authorization\"] = f\"Bearer {token}\"\n        resp = requests.get(url, headers=headers)\n    else:\n        raise","preventionTips":["Token-strip and dequote secrets loaded from files or .env (read().strip()).","Copy the token value only from the same environment the server runs in.","Rotate tokens in lockstep: update server and all clients in one change.","Beware trailing spaces after 'Bearer ' in hand-built header strings."],"tags":["http","auth","security","token"],"backgroundTag":"invalid-api-token","analyzedSha":"ae57a2357745a9706cb12d0fd76d954c84d166fa","analyzedAt":"2026-08-30T02:49:05.834Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}