Panniantong/Agent-Reach · error · ConfigReadOnlyError

当前配置是只读的,不能修改

Error message

当前配置是只读的,不能修改

What it means

Raised by Config.set() (agent_reach/config.py:173) when the Config instance was created with read_only=True. Read-only mode exists so callers (e.g. concurrent sessions or sandboxed/agent contexts) can inspect config without risking writes; any mutation via set() is rejected before the in-memory dict is touched. The Chinese message '当前配置是只读的,不能修改' means 'the current config is read-only and cannot be modified'.

Source

Thrown at agent_reach/config.py:173

            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_val
        return default

    def set(self, key: str, value: Any):
        """Set a config value and save."""
        if self.read_only:
            raise ConfigReadOnlyError("当前配置是只读的,不能修改")
        missing = object()
        previous = self.data.get(key, missing)
        self.data[key] = value
        try:
            self.save()
        except BaseException:
            if previous is missing:
                self.data.pop(key, None)
            else:
                self.data[key] = previous
            raise

    def delete(self, key: str):
        """Delete a config key and save."""
        if self.read_only:
            raise ConfigReadOnlyError("当前配置是只读的,不能修改")
        missing = object()
        previous = self.data.pop(key, missing)

View on GitHub (pinned to 93ae1d18c3)

Solutions

  1. Create or obtain a writable Config instance (read_only defaults to False) before calling set()
  2. Check cfg.read_only before attempting writes and surface a clear message to the user
  3. If the write must persist, route it through the CLI (`agent-reach configure <key>`) instead of mutating a read-only handle
  4. Catch agent_reach.config.ConfigReadOnlyError and fail fast instead of silently skipping the save

Example fix

# before
from agent_reach.config import Config
cfg = Config(read_only=True)
cfg.set('twitter_cookies', raw)  # raises ConfigReadOnlyError

# after
cfg = Config()  # writable instance
cfg.set('twitter_cookies', raw)
Defensive patterns

Strategy: type-guard

Validate before calling

if cfg.read_only:
    raise PermissionError('config handle is read-only; open a writable Config()')

Type guard

def is_writable_config(cfg) -> bool:
    return not getattr(cfg, 'read_only', False)

Try / catch

from agent_reach.config import ConfigReadOnlyError
try:
    cfg.set(key, value)
except ConfigReadOnlyError:
    # open a writable instance instead of mutating the shared handle
    writable = Config(); writable.set(key, value)

Prevention

When it happens

Trigger: Calling cfg.set('key', value) on a Config constructed with Config(..., read_only=True) — typically instances obtained from a read-only accessor or explicitly instantiated with that flag.

Common situations: An agent or script grabbed a shared read-only Config handle and then tried to store credentials; refactoring code that previously used a writable instance; tests that build Config with read_only=True for safety but later need to write.

Related errors


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