Panniantong/Agent-Reach · error · GitHubConfigError

gh hosts.yml 不是有效的 UTF-8 YAML

Error message

gh hosts.yml 不是有效的 UTF-8 YAML

What it means

Raised when yaml.safe_load() on the already-read hosts.yml content throws yaml.YAMLError. The file was read and UTF-8-decoded successfully, but the text is not parseable YAML (bad indentation, stray tabs, unclosed quotes/brackets).

Source

Thrown at agent_reach/channels/github.py:66

    return Path.home() / ".config" / "gh" / "hosts.yml"


def _saved_github_host_configured() -> bool:
    """Inspect github.com's hosts.yml entry without executing gh."""
    hosts_path = _gh_hosts_path()
    try:
        raw = read_small_text_no_follow(
            hosts_path,
            max_bytes=_MAX_HOSTS_BYTES,
        )
    except (OSError, PrivatePathError, UnicodeError) as exc:
        raise GitHubConfigError("gh hosts.yml 无法安全读取") from exc
    if raw is None:
        return False
    try:
        payload = yaml.safe_load(raw)
    except yaml.YAMLError as exc:
        raise GitHubConfigError("gh hosts.yml 不是有效的 UTF-8 YAML") from exc
    if payload is None:
        return False
    if not isinstance(payload, dict):
        raise GitHubConfigError("gh hosts.yml 顶层必须是对象")

    host = payload.get("github.com")
    if host is None:
        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:

View on GitHub (pinned to 93ae1d18c3)

Solutions

  1. Validate the file: python -c "import yaml,sys; yaml.safe_load(open(sys.argv[1]))" ~/.config/gh/hosts.yml
  2. Fix indentation (spaces only, 2 per level) and quoting; typical shape is 'github.com:\n oauth_token: ...\n user: ...'
  3. Regenerate the file with `gh auth login` if hand-repair fails
  4. Keep the file under _MAX_HOSTS_BYTES and free of non-UTF-8 bytes (save as UTF-8)

Example fix

# before (invalid: tab indentation)
 github.com:
	oauth_token: gho_xxx
# after
 github.com:
   oauth_token: gho_xxx
   user: you
Defensive patterns

Strategy: validation

Validate before calling

import yaml

def hosts_yaml_ok(path) -> bool:
    try:
        with open(path, "r", encoding="utf-8") as fh:
            return isinstance(yaml.safe_load(fh), (dict, type(None)))
    except (OSError, UnicodeError, yaml.YAMLError):
        return False

Try / catch

try:
    _saved_github_host_configured()
except GitHubConfigError as exc:
    log_warning(f"gh config unreadable: {exc}; run `gh auth login`")

Prevention

When it happens

Trigger: Calling the GitHub credential probe with a hosts.yml whose text is malformed YAML: tabs used for indentation, a truncated file, hand-edited structure errors, or an empty scalar where a mapping is expected mid-document.

Common situations: Manual editing of hosts.yml to add a second account; a partially-written file after a crash or concurrent `gh auth login`; copy-paste from a browser introducing smart quotes; secret-injection tooling mangling the file.

Related errors


AI-assisted analysis of Panniantong/Agent-Reach@93ae1d18c3 (2026-08-14). Data as JSON: /api/errors/8427fe818c7ccb0d. Report an issue: GitHub.