FoundationAgents/MetaGPT · error · ValueError
`access_token` is invalid. Visit: "https://github.com/settin
Error message
`access_token` is invalid. Visit: "https://github.com/settings/tokens"
What it means
Raised by GitRepository.push() (metagpt/utils/git_repository.py:273): the method needs credentials to push and neither the `auth` object nor the `access_token` string argument was supplied. It deliberately fails before running any git command so tokens are never taken from thin air.
Source
Thrown at metagpt/utils/git_repository.py:273
new_branch (str): The name of the new branch to be pushed.
comments (str, optional): Comments to be associated with the push. Defaults to "Archive".
access_token (str, optional): Access token for authentication. Defaults to None. Visit `https://pygithub.readthedocs.io/en/latest/examples/Authentication.html`, `https://github.com/PyGithub/PyGithub/blob/main/doc/examples/Authentication.rst`.
auth (Auth, optional): Optional authentication object. Defaults to None.
Returns:
GitBranch: The pushed branch object.
Raises:
ValueError: If neither `auth` nor `access_token` is provided.
BadCredentialsException: If authentication fails due to bad credentials or timeout.
Note:
This function assumes that `self.current_branch`, `self.new_branch()`, `self.archive()`,
`ctx.config.proxy`, `ctx.config`, `self.remote_url`, `shell_execute()`, and `logger` are
defined and accessible within the scope of this function.
"""
if not auth and not access_token:
raise ValueError('`access_token` is invalid. Visit: "https://github.com/settings/tokens"')
from metagpt.context import Context
base = self.current_branch
head = base if not new_branch else self.new_branch(new_branch)
self.archive(comments) # will skip committing if no changes
ctx = Context()
env = ctx.new_environ()
proxy = ["-c", f"http.proxy={ctx.config.proxy}"] if ctx.config.proxy else []
token = access_token or auth.token
remote_url = f"https://{token}@" + self.remote_url.removeprefix("https://")
command = ["git"] + proxy + ["push", remote_url]
logger.info(" ".join(command).replace(token, "<TOKEN>"))
try:
stdout, stderr, return_code = await shell_execute(
command=command, cwd=str(self.workdir), env=env, timeout=15
)
except TimeoutExpired as e:
info = str(e).replace(token, "<TOKEN>")View on GitHub (pinned to 11cdf466d0)
Solutions
- Pass a GitHub personal access token: repo.push(new_branch='x', comments='y', access_token=os.environ['GITHUB_TOKEN']).
- Or pass a PyGithub Auth object via the auth parameter.
- Create the token at https://github.com/settings/tokens with repo scope and store it in an env var / devkey rather than in code.
Example fix
# before repo.push(new_branch='feature', comments='update') # ValueError # after import os repo.push(new_branch='feature', comments='update', access_token=os.environ['METAGPT_GIT_TOKEN'])
Defensive patterns
Strategy: validation
Validate before calling
import os
token = os.environ.get('METAGPT_GIT_TOKEN') or os.environ.get('GITHUB_TOKEN')
if not token:
raise SystemExit('Set METAGPT_GIT_TOKEN to enable git push') Type guard
def can_push(access_token: str | None, auth) -> bool:
return bool(access_token or auth) Try / catch
try:
repo.push(new_branch=branch, comments=msg, access_token=token)
except ValueError as e:
if 'access_token' in str(e):
logger.error('No git credentials configured; push skipped') Prevention
- Store the PAT in an env var or devkey and always pass it explicitly.
- Fail fast at process start if push is expected but no token is present.
- Give the token repo scope and an expiry; rotate regularly.
When it happens
Trigger: Calling repo.push(new_branch='feat', comments='...') with no access_token and no auth argument. The token cannot be inferred from the repository URL or global config at this point.
Common situations: Automation/agent runs (e.g. after DocumentGenerator or code generation) that expect a GitHub token from the environment but none was configured; scripts migrated from an older version that read METAGPT_GIT_TOKEN implicitly.
AI-assisted analysis of FoundationAgents/MetaGPT@11cdf466d0 (2026-08-14).
Data as JSON: /api/errors/89ee600228023394.
Report an issue: GitHub.