google-gemini/gemini-cli · critical · GitHubClientError

GitHub token is missing. Cannot authorize Pull Request creat

Error message

GitHub token is missing. Cannot authorize Pull Request creation.

What it means

GitHubClientError 'GitHub token is missing. Cannot authorize Pull Request creation.' is raised by create_pull_request when self._token is falsy. The PR endpoint requires a Bearer token; without one the request would 401, so the client fails fast with a clear message before any network call.

Source

Thrown at tools/caretaker-agent/cloudrun/pr-generator/workflow/github_client.py:50

    def create_pull_request(
        self, branch_name: str, title: str, body: str
    ) -> str:
        """Submits a POST request to GitHub to create a new Pull Request.

        Args:
            branch_name: The feature branch to be merged.
            title: Title of the Pull Request.
            body: Body description markdown of the Pull Request.

        Returns:
            The PR number of the successfully created Pull Request as a string.

        Raises:
            GitHubClientError: If the HTTP request fails or token is missing.
        """
        if not self._token:
            raise GitHubClientError(
                "GitHub token is missing. Cannot authorize Pull Request creation."
            )

        data = {
            "title": title,
            "body": body,
            "head": branch_name,
            "base": "main",
        }

        req = urllib.request.Request(
            self._base_url,
            data=json.dumps(data).encode("utf-8"),
            headers={
                "Accept": "application/vnd.github+json",
                "Authorization": f"Bearer {self._token}",
                "X-GitHub-Api-Version": "2022-11-28",
                "Content-Type": "application/json",

View on GitHub (pinned to 5024443c72)

Solutions

  1. Set GH_TOKEN (or whichever var the GitHubClient is constructed from) in the CloudRun service env / secret mount.
  2. Construct GitHubClient with a non-empty token: GitHubClient(token=os.environ['GH_TOKEN'], owner=..., repo=...).
  3. Add a startup assertion that the token is present so the failure surfaces at boot, not at first PR.

Example fix

# before
client = GitHubClient(token=os.environ.get('GH_TOKEN'), owner=o, repo=r)
# after
token = os.environ['GH_TOKEN']  # KeyError surfaces the missing secret early
client = GitHubClient(token=token, owner=o, repo=r)
Defensive patterns

Strategy: validation

Validate before calling

token = os.environ.get('GH_TOKEN') or os.environ.get('GITHUB_TOKEN')
if not token:
    raise SystemExit('GH_TOKEN env var required to create PRs')

Type guard

def is_missing_github_token(e: Exception) -> bool:
    return isinstance(e, GitHubClientError) and 'token is missing' in str(e).lower()

Try / catch

try:
    pr_number = client.create_pull_request(branch, title, body)
except GitHubClientError as e:
    if 'token is missing' in str(e): raise SystemExit('configure GH_TOKEN secret')
    raise

Prevention

When it happens

Trigger: GitHubClient(token=None or '') constructed -> create_pull_request(...) -> `if not self._token: raise GitHubClientError(...)` at line 49-52, before building the urllib Request.

Common situations: GH_TOKEN/GITHUB_TOKEN env var not injected into the CloudRun service; secret name typo in the deploy config; token injected as empty string; the workflow's token-load step ran before the env var was exported.

Related errors


AI-assisted analysis of google-gemini/gemini-cli@5024443c72 (2026-08-12). Data as JSON: /api/errors/1e8b214d0f0a3661. Report an issue: GitHub.