{"record":{"id":"62a7c4ffbe7cdc78","repo":"Panniantong/Agent-Reach","slug":"error-62a7c4","errorCode":null,"errorMessage":"当前配置是只读的，不能修改","messagePattern":"当前配置是只读的，不能修改","errorType":"exception","errorClass":"ConfigReadOnlyError","httpStatus":null,"severity":"error","filePath":"agent_reach/config.py","lineNumber":173,"sourceCode":"            raise ConfigReadOnlyError(\"当前配置是只读的，不能保存\")\n        self._ensure_dir()\n        _atomic_write_yaml(self.config_path, self.data)\n\n    def get(self, key: str, default: Any = None) -> Any:\n        \"\"\"Get a config value. Also checks environment variables (uppercase).\"\"\"\n        # Config file first\n        if key in self.data:\n            return self.data[key]\n        # Then env var (uppercase)\n        env_val = os.environ.get(key.upper())\n        if env_val:\n            return env_val\n        return default\n\n    def set(self, key: str, value: Any):\n        \"\"\"Set a config value and save.\"\"\"\n        if self.read_only:\n            raise ConfigReadOnlyError(\"当前配置是只读的，不能修改\")\n        missing = object()\n        previous = self.data.get(key, missing)\n        self.data[key] = value\n        try:\n            self.save()\n        except BaseException:\n            if previous is missing:\n                self.data.pop(key, None)\n            else:\n                self.data[key] = previous\n            raise\n\n    def delete(self, key: str):\n        \"\"\"Delete a config key and save.\"\"\"\n        if self.read_only:\n            raise ConfigReadOnlyError(\"当前配置是只读的，不能修改\")\n        missing = object()\n        previous = self.data.pop(key, missing)","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/Panniantong/Agent-Reach/blob/93ae1d18c37b707dec053c7c4f9d91cd8ef8943d/agent_reach/config.py#L155-L191","documentation":"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'.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Create or obtain a writable Config instance (read_only defaults to False) before calling set()","Check cfg.read_only before attempting writes and surface a clear message to the user","If the write must persist, route it through the CLI (`agent-reach configure <key>`) instead of mutating a read-only handle","Catch agent_reach.config.ConfigReadOnlyError and fail fast instead of silently skipping the save"],"exampleFix":"# before\nfrom agent_reach.config import Config\ncfg = Config(read_only=True)\ncfg.set('twitter_cookies', raw)  # raises ConfigReadOnlyError\n\n# after\ncfg = Config()  # writable instance\ncfg.set('twitter_cookies', raw)","handlingStrategy":"type-guard","validationCode":"if cfg.read_only:\n    raise PermissionError('config handle is read-only; open a writable Config()')","typeGuard":"def is_writable_config(cfg) -> bool:\n    return not getattr(cfg, 'read_only', False)","tryCatchPattern":"from agent_reach.config import ConfigReadOnlyError\ntry:\n    cfg.set(key, value)\nexcept ConfigReadOnlyError:\n    # open a writable instance instead of mutating the shared handle\n    writable = Config(); writable.set(key, value)","preventionTips":["Pass read_only=True only to consumers that never write","Centralize writes in one helper that checks cfg.read_only first","Prefer the CLI `agent-reach configure` for user-driven changes"],"tags":["config","read-only","state-mutation"],"backgroundTag":null,"analyzedSha":"93ae1d18c37b707dec053c7c4f9d91cd8ef8943d","analyzedAt":"2026-08-14T22:54:06.735Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}