{"record":{"id":"fb87ac13e560bee7","repo":"BigPizzaV3/CodexPlusPlus","slug":"codex-config-must-be-an-object","errorCode":null,"errorMessage":"codex config must be an object","messagePattern":"codex config must be an object","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"tools/codex-wechat/codex_wechat.py","lineNumber":119,"sourceCode":"            with LOG_FILE.open(\"a\", encoding=\"utf-8\") as f:\n                f.write(line + \"\\n\")\n        except Exception:\n            pass\n\n\ndef load_json_file(path: Path) -> dict[str, Any]:\n    with path.open(\"r\", encoding=\"utf-8\") as f:\n        data = json.load(f)\n    if not isinstance(data, dict):\n        raise ValueError(f\"{path} must contain a JSON object\")\n    return data\n\n\ndef load_config(path: Path) -> BridgeConfig:\n    raw = load_json_file(path)\n    codex_raw = raw.get(\"codex\") or {}\n    if not isinstance(codex_raw, dict):\n        raise ValueError(\"codex config must be an object\")\n\n    cfg = BridgeConfig(\n        base_url=str(raw.get(\"base_url\") or ILINK_BASE_URL),\n        token=str(raw.get(\"token\") or \"\"),\n        account_id=str(raw.get(\"account_id\") or \"\"),\n        allow_all=bool(raw.get(\"allow_all\", False)),\n        allow_user_ids=set(str(x) for x in raw.get(\"allow_user_ids\") or []),\n        require_prefix=bool(raw.get(\"require_prefix\", True)),\n        prefix=str(raw.get(\"prefix\") or \"/codex\"),\n        allow_id_command_for_unauthorized=bool(\n            raw.get(\"allow_id_command_for_unauthorized\", True)\n        ),\n        poll_timeout_seconds=int(raw.get(\"poll_timeout_seconds\", 35)),\n        retry_delay_seconds=int(raw.get(\"retry_delay_seconds\", 2)),\n        backoff_delay_seconds=int(raw.get(\"backoff_delay_seconds\", 30)),\n        max_consecutive_failures=int(raw.get(\"max_consecutive_failures\", 3)),\n        max_reply_chars=int(raw.get(\"max_reply_chars\", 1800)),\n        enable_typing=bool(raw.get(\"enable_typing\", True)),","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/BigPizzaV3/CodexPlusPlus/blob/b1ed92e5e4a2d74095d4b8db5af43cef7acba9c6/tools/codex-wechat/codex_wechat.py#L101-L137","documentation":"load_config reads the config.toml-shaped JSON file and requires the top-level `codex` key to be a JSON object. It fires when the user's config file has a `codex` entry that is a string, number, array, or null (explicit `{}` is fine), meaning the bridge cannot extract nested fields like codex.command/args/timeouts from it.","triggerScenarios":"Thrown at tools/codex-wechat/codex_wechat.py:119 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Open the config file and change the `codex` value to a JSON object, e.g. \"codex\": {\"command\": \"codex\", \"args\": [\"app-server\"]}.","If `codex` is not needed, remove the key entirely — the code falls back to raw.get(\"codex\") or {}.","Validate the file with a JSON linter to ensure no quoting mistakes turned the object into a string."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"b1ed92e5e4a2d74095d4b8db5af43cef7acba9c6","analyzedAt":"2026-09-19T23:35:21.129Z","contentChangedAt":"2026-09-19T23:35:21.129Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}