Panniantong/Agent-Reach · error · GitHubConfigError
Agent Reach 的 GitHub 配置无法读取
Error message
Agent Reach 的 GitHub 配置无法读取
What it means
Raised by _explicit_github_credentials() when calling config.get('github_token') on the Agent Reach config object raises an unexpected exception. GH_TOKEN/GITHUB_TOKEN env vars and a None config are handled before this; only a config object whose .get() itself blows up (broken Mapping subclass, hostile __getitem__/__getattribute__, properties raising) reaches here.
Source
Thrown at agent_reach/channels/github.py:92
return False
if not isinstance(host, dict):
raise GitHubConfigError("gh hosts.yml 的 github.com 配置无效")
users = host.get("users")
if users is not None and not isinstance(users, dict):
raise GitHubConfigError("gh hosts.yml 的 users 配置无效")
return bool(host.get("oauth_token") or host.get("user") or users)
def _explicit_github_credentials(config) -> bool:
if any(os.environ.get(name) for name in ("GH_TOKEN", "GITHUB_TOKEN")):
return True
if config is None:
return False
try:
return bool(config.get("github_token"))
except Exception as exc:
raise GitHubConfigError("Agent Reach 的 GitHub 配置无法读取") from exc
class GitHubChannel(Channel):
name = "github"
description = "GitHub 仓库和代码"
backends = ["gh CLI"]
tier = 0
def can_handle(self, url: str) -> bool:
from agent_reach.utils.url import host_matches
return host_matches(url, "github.com")
def check(self, config=None):
self.active_backend = None
probe = probe_command(
"gh",
["--version"],View on GitHub (pinned to 93ae1d18c3)
Solutions
- Pass the standard config object produced by agent_reach.config, or a plain dict
- If wrapping config, ensure get(key, default=None) is delegated to the underlying dict without raising
- Simpler: set GH_TOKEN/GITHUB_TOKEN in the environment — that path returns before config is touched
Example fix
# before
channel.check(config=MyStrictConfig()) # .get() raises
# after
channel.check(config={"github_token": "ghp_..."}) # or use agent_reach.config.load() Defensive patterns
Strategy: type-guard
Validate before calling
def is_plain_mapping(cfg) -> bool:
return isinstance(cfg, dict) or (hasattr(cfg, "get") and callable(cfg.get) and not isinstance(cfg, (str, list, set))) Type guard
from typing import Any, Mapping
def is_safe_config(obj: Any) -> "typeguard[Mapping]":
return isinstance(obj, Mapping) Try / catch
from agent_reach.channels.github import GitHubConfigError
try:
ok = _explicit_github_credentials(config)
except GitHubConfigError:
ok = False # or replace config with {} and retry once Prevention
- Pass plain dicts or agent_reach.config's object to channel APIs
- Prefer GH_TOKEN/GITHUB_TOKEN env vars over config plumbing
- Never hand channel.check() objects that validate/raise on get()
When it happens
Trigger: Passing a custom config object (not a plain dict / the YAML-backed Config class) whose get() raises — e.g. a dataclass without get, a Mapping that validates keys and throws, a mock raising in get. Env vars unset and config is not None.
Common situations: Embedding Agent Reach with a homegrown config wrapper; config loaded from a corrupted dataclass; test doubles that raise on unexpected attribute access.
Related errors
- gh hosts.yml 无法安全读取
- gh hosts.yml 不是有效的 UTF-8 YAML
- gh hosts.yml 顶层必须是对象
- gh hosts.yml 的 github.com 配置无效
- gh hosts.yml 的 users 配置无效
AI-assisted analysis of Panniantong/Agent-Reach@93ae1d18c3 (2026-08-14).
Data as JSON: /api/errors/5166aca869dba1f3.
Report an issue: GitHub.