Panniantong/Agent-Reach · error · ConfigError
配置文件顶层必须是对象
Error message
配置文件顶层必须是对象
What it means
Config.load() parses ~/.agent-reach/config.yaml with yaml.safe_load and requires the top-level node to be a mapping. If the file's top level is a list, scalar, or string, ConfigError('配置文件顶层必须是对象') ('the config file top level must be an object') is raised on every Config construction that loads.
Source
Thrown at agent_reach/config.py:149
def load(self):
"""Load config from YAML file."""
_reject_symlink(self.config_dir, "配置目录")
_reject_symlink(self.config_path, "配置文件")
try:
payload = read_small_text_no_follow(
self.config_path,
max_bytes=_MAX_CONFIG_BYTES,
)
except PrivatePathError as exc:
raise ConfigSecurityError(str(exc)) from exc
if payload is None:
self.data = {}
return
loaded = yaml.safe_load(payload) or {}
if not isinstance(loaded, dict):
raise ConfigError("配置文件顶层必须是对象")
self.data = loaded
def save(self):
"""Save config atomically, refusing mutation in read-only mode."""
if self.read_only:
raise ConfigReadOnlyError("当前配置是只读的,不能保存")
self._ensure_dir()
_atomic_write_yaml(self.config_path, self.data)
def get(self, key: str, default: Any = None) -> Any:
"""Get a config value. Also checks environment variables (uppercase)."""
# Config file first
if key in self.data:
return self.data[key]
# Then env var (uppercase)
env_val = os.environ.get(key.upper())
if env_val:
return env_valView on GitHub (pinned to 93ae1d18c3)
Solutions
- Open ~/.agent-reach/config.yaml and ensure the first non-comment line is a key like 'twitter_cookies: ...', not a '- ' list item or plain text
- Validate locally: python -c "import yaml,sys; d=yaml.safe_load(open('/home/you/.agent-reach/config.yaml')); print(type(d))" — must print <class 'dict'>
- If unsure, back up and recreate: mv config.yaml config.yaml.bak, then run `agent-reach configure` for each key you need
- Never write the config by hand redirection; use `agent-reach configure <key>` which writes valid YAML atomically
Example fix
# before (~/.agent-reach/config.yaml root is a list) - github_token: ghp_xxx - proxy: http://127.0.0.1:7890 # after (root is a mapping) github_token: ghp_xxx proxy: http://127.0.0.1:7890
Defensive patterns
Strategy: try-catch
Validate before calling
import yaml
from pathlib import Path
def config_is_valid_mapping(path: Path) -> bool:
if not path.exists():
return True # absent file is fine; Config treats it as empty
loaded = yaml.safe_load(path.read_text(encoding="utf-8"))
return loaded is None or isinstance(loaded, dict) Try / catch
from agent_reach.config import Config, ConfigError
try:
cfg = Config()
cfg.load()
except ConfigError as exc:
if "顶层必须是对象" in str(exc):
quarantine_and_recreate_config() # mv bad file aside, reconfigure keys
else:
raise Prevention
- Only mutate the config through `agent-reach configure <key>`, which writes valid YAML atomically
- After any hand edit, validate with yaml.safe_load and assert the result is a dict
- Keep the root as key: value pairs — never wrap the document in a list
When it happens
Trigger: A config.yaml whose root is '- key: value' (list), a bare string, or an empty-but-quoted document after hand-editing; files created by redirecting output (`echo something > ~/.agent-reach/config.yaml`); YAML with a document separator producing a non-map root.
Common situations: Hand-editing the config and accidentally wrapping everything in a list; scripts generating YAML with a top-level sequence; partial writes from a crash leaving a truncated non-map document; copy-pasting a YAML fragment that starts with '-'.
Related errors
- gh hosts.yml 不是有效的 UTF-8 YAML
- gh hosts.yml 顶层必须是对象
- gh hosts.yml 的 github.com 配置无效
- gh hosts.yml 的 users 配置无效
- {label}不能经过符号链接:{current}
AI-assisted analysis of Panniantong/Agent-Reach@93ae1d18c3 (2026-08-14).
Data as JSON: /api/errors/c5ef1388bf5e6496.
Report an issue: GitHub.