{"record":{"id":"07cd4f2dbc2cca09","repo":"Aider-AI/aider","slug":"github-copilot-token-environment-variable-is-empty","errorCode":null,"errorMessage":"GITHUB_COPILOT_TOKEN environment variable is empty","messagePattern":"GITHUB_COPILOT_TOKEN environment variable is empty","errorType":"exception","errorClass":"KeyError","httpStatus":null,"severity":"critical","filePath":"aider/models.py","lineNumber":956,"sourceCode":"\n        if openai_api_key not in os.environ or (\n            int(dict(x.split(\"=\") for x in os.environ[openai_api_key].split(\";\"))[\"exp\"])\n            < int(datetime.now().timestamp())\n        ):\n            import requests\n\n            class GitHubCopilotTokenError(Exception):\n                \"\"\"Custom exception for GitHub Copilot token-related errors.\"\"\"\n\n                pass\n\n            # Validate GitHub Copilot token exists\n            if \"GITHUB_COPILOT_TOKEN\" not in os.environ:\n                raise KeyError(\"GITHUB_COPILOT_TOKEN environment variable not found\")\n\n            github_token = os.environ[\"GITHUB_COPILOT_TOKEN\"]\n            if not github_token.strip():\n                raise KeyError(\"GITHUB_COPILOT_TOKEN environment variable is empty\")\n\n            headers = {\n                \"Authorization\": f\"Bearer {os.environ['GITHUB_COPILOT_TOKEN']}\",\n                \"Editor-Version\": extra_headers[\"Editor-Version\"],\n                \"Copilot-Integration-Id\": extra_headers[\"Copilot-Integration-Id\"],\n                \"Content-Type\": \"application/json\",\n            }\n\n            url = \"https://api.github.com/copilot_internal/v2/token\"\n            res = requests.get(url, headers=headers)\n            if res.status_code != 200:\n                safe_headers = {k: v for k, v in headers.items() if k != \"Authorization\"}\n                token_preview = github_token[:5] + \"...\" if len(github_token) >= 5 else github_token\n                safe_headers[\"Authorization\"] = f\"Bearer {token_preview}\"\n                raise GitHubCopilotTokenError(\n                    f\"GitHub Copilot API request failed (Status: {res.status_code})\\n\"\n                    f\"URL: {url}\\n\"\n                    f\"Headers: {json.dumps(safe_headers, indent=2)}\\n\"","sourceCodeStart":938,"sourceCodeEnd":974,"githubUrl":"https://github.com/Aider-AI/aider/blob/5dc9490bb35f9729ef2c95d00a19ccd30c26339c/aider/models.py#L938-L974","documentation":"Companion check to the missing-variable error in aider/models.py: GITHUB_COPILOT_TOKEN exists in the environment but its value is empty or whitespace-only (github_token.strip() is falsy). It raises KeyError('GITHUB_COPILOT_TOKEN environment variable is empty'). The distinction matters diagnostically: the variable is exported but holds no usable credential — typically an empty-string assignment or a botched copy/paste into a dotfile.","triggerScenarios":"Running with a Copilot model after 'export GITHUB_COPILOT_TOKEN=' (empty assignment), setting it to ''/'   ' in a .env-style loader, or a CI secret that was defined with no value. Triggered at first Copilot model call whose cached token is expired, same lazy path as the missing-variable check.","commonSituations":"Dotfiles with a placeholder line like export GITHUB_COPILOT_TOKEN= awaiting manual fill-in; docker-compose environment entries mapping an unset CI variable; secrets managers returning empty strings for unset keys.","solutions":["Check the current value without printing it: [ -n \"$GITHUB_COPILOT_TOKEN\" ] && echo set || echo empty — then re-export the real token.","Search shell rc files and .env files for an empty assignment to GITHUB_COPILOT_TOKEN and fix or remove the placeholder line.","In CI, verify the secret is actually attached to the job and non-empty before invoking aider."],"exampleFix":"# before\nexport GITHUB_COPILOT_TOKEN=\n\n# after\nexport GITHUB_COPILOT_TOKEN=\"$(cat ~/.config/aider/copilot_token)\"  # real token\n# verify without exposing the value:\n[ -n \"$GITHUB_COPILOT_TOKEN\" ] && echo \"token set\"","handlingStrategy":"validation","validationCode":"import os\n\ndef assert_copilot_token_nonempty():\n    tok = os.environ.get(\"GITHUB_COPILOT_TOKEN\", \"\")\n    if not tok.strip():\n        raise SystemExit(\n            \"GITHUB_COPILOT_TOKEN is empty. Re-export a real token:\\n\"\n            \"  export GITHUB_COPILOT_TOKEN=<token>\"\n        )","typeGuard":null,"tryCatchPattern":"try:\n    result = model.simple_send_with_retries(msgs)\nexcept KeyError as e:\n    if \"GITHUB_COPILOT_TOKEN\" in str(e):\n        # covers both 'not found' and 'is empty' variants\n        print(\"Copilot credential missing/empty — fix env and retry\")\n    raise","preventionTips":["After exporting, verify non-emptiness without printing: [ -n \"$GITHUB_COPILOT_TOKEN\" ] || echo empty.","Grep dotfiles/.env for placeholder assignments (VAR= with no value) that shadow real ones.","In CI, fail the job early if the secret is unset rather than at first model call."],"tags":["authentication","environment-variables","github-copilot","empty-value","aider"],"backgroundTag":null,"analyzedSha":"5dc9490bb35f9729ef2c95d00a19ccd30c26339c","analyzedAt":"2026-08-15T05:40:10.498Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}