{"record":{"id":"980ca83bbbc420a5","repo":"Zie619/n8n-workflows","slug":"invalid-authentication-token","errorCode":null,"errorMessage":"Invalid authentication token","messagePattern":"Invalid authentication token","errorType":"http","errorClass":"HTTPException","httpStatus":401,"severity":"error","filePath":"api_server.py","lineNumber":603,"sourceCode":"            status_code=429, detail=\"Rate limit exceeded. Please try again later.\"\n        )\n\n    # Security: Basic authentication check\n    # In production, use proper authentication (JWT, OAuth, etc.)\n    # For now, check for environment variable or disable endpoint\n\n    expected_token = os.environ.get(\"ADMIN_TOKEN\", None)\n\n    if not expected_token:\n        # If no token is configured, disable the endpoint for security\n        raise HTTPException(\n            status_code=503,\n            detail=\"Reindexing endpoint is disabled. Set ADMIN_TOKEN environment variable to enable.\",\n        )\n\n    if admin_token != expected_token:\n        print(f\"Security: Unauthorized reindex attempt from {client_ip}\")\n        raise HTTPException(status_code=401, detail=\"Invalid authentication token\")\n\n    def run_indexing():\n        try:\n            db.index_all_workflows(force_reindex=force)\n            print(f\"Reindexing completed successfully (requested by {client_ip})\")\n        except Exception as e:\n            print(f\"Error during reindexing: {e}\")\n\n    background_tasks.add_task(run_indexing)\n    return {\"message\": \"Reindexing started in background\", \"requested_by\": client_ip}\n\n\n@app.get(\"/api/integrations\")\nasync def get_integrations():\n    \"\"\"Get list of all unique integrations.\"\"\"\n    try:\n        stats = db.get_stats()\n        # For now, return basic info. Could be enhanced to return detailed integration stats","sourceCodeStart":585,"sourceCodeEnd":621,"githubUrl":"https://github.com/Zie619/n8n-workflows/blob/94007c1445d9258a7da116646b79473e7c7c3282/api_server.py#L585-L621","documentation":"Raised by the admin reindex endpoint in api_server.py when the supplied admin_token does not equal the ADMIN_TOKEN environment variable. It is a deliberate 401 authentication rejection protecting a destructive/background indexing operation. The server also logs 'Security: Unauthorized reindex attempt from {client_ip}' whenever it fires.","triggerScenarios":"POST to the reindex endpoint (e.g. /api/reindex?force=true) with a missing, misspelled, or stale admin_token argument while ADMIN_TOKEN is set in the server environment. Also triggered when the client sends a token computed against a different ADMIN_TOKEN value than the one the server process was started with.","commonSituations":"ADMIN_TOKEN was rotated or differs between environments (dev vs prod); the server was restarted with a new env var but the client still uses the old token; the token is passed as a header while the endpoint expects it as a query/body parameter (or vice versa); trailing whitespace/newline in the env var from a .env file.","solutions":["Confirm the exact value of ADMIN_TOKEN in the server process environment (print len() or a hash, never the value) and re-send a token that matches it exactly.","Check how the endpoint declares the admin_token parameter (query vs header vs body) and send it in that position.","Strip whitespace when setting the env var: export ADMIN_TOKEN=$(cat token.txt | tr -d '[:space:]') or fix the .env line.","If ADMIN_TOKEN is unset you will instead get a 503 'endpoint is disabled' — set the variable to enable the endpoint, then authenticate."],"exampleFix":"# before\nresp = requests.post(\"http://host/api/reindex\", params={\"force\": True})  # 401: no token\n\n# after\nimport os\nresp = requests.post(\n    \"http://host/api/reindex\",\n    params={\"force\": True, \"admin_token\": os.environ[\"ADMIN_TOKEN\"]},\n)","handlingStrategy":"validation","validationCode":"import os\n\ndef can_reindex() -> tuple[bool, str]:\n    token = os.environ.get(\"ADMIN_TOKEN\")\n    if not token:\n        return False, \"ADMIN_TOKEN not set on client; endpoint will return 503/401\"\n    return True, token\n\n# before the call:\nok, token = can_reindex()\nif ok:\n    requests.post(f\"{BASE}/api/reindex\", params={\"admin_token\": token, \"force\": False})","typeGuard":null,"tryCatchPattern":"try:\n    resp = requests.post(url, params={\"admin_token\": token}, timeout=30)\n    resp.raise_for_status()\nexcept requests.HTTPError as e:\n    status = e.response.status_code\n    if status == 401:\n        # credential mismatch: re-read ADMIN_TOKEN from source of truth, never retry in a loop\n        raise RuntimeError(\"Admin token rejected; refresh credential\") from e\n    if status == 503:\n        raise RuntimeError(\"Endpoint disabled; ADMIN_TOKEN unset on server\") from e\n    raise","preventionTips":["Load the admin token from a secrets manager or env file at call time instead of hardcoding a copy that drifts.","Never retry a 401 automatically — treat it as a credential bug, not a transient failure.","Alert on the server log line 'Security: Unauthorized reindex attempt' to catch misconfigured clients early."],"tags":["authentication","security","http-401","fastapi","environment-variables"],"backgroundTag":null,"analyzedSha":"94007c1445d9258a7da116646b79473e7c7c3282","analyzedAt":"2026-08-15T04:10:37.591Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}