{"record":{"id":"b07a2c72dbabe25e","repo":"HKUDS/Vibe-Trading","slug":"each-local-connection-must-be-an-object","errorCode":null,"errorMessage":"each local connection must be an object","messagePattern":"each local connection must be an object","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/trading/connections.py","lineNumber":303,"sourceCode":"        return result\n\n    @staticmethod\n    def _parse(raw: object) -> TradingConnection:\n        \"\"\"Validate one registry row.\n\n        Args:\n            raw: Decoded registry row.\n\n        Returns:\n            The validated connection.\n\n        Raises:\n            ValueError: If the row is not an object, carries an invalid id or\n                label, names an unknown or ineligible profile, or claims a\n                credential reference that does not match its transport.\n        \"\"\"\n        if not isinstance(raw, dict):\n            raise ValueError(\"each local connection must be an object\")\n        connection_id = str(raw.get(\"id\") or \"\").strip().lower()\n        if not _ID_RE.fullmatch(connection_id):\n            raise ValueError(f\"invalid local connection id: {connection_id or '?'}\")\n        profile_id = str(raw.get(\"profile_id\") or \"\").strip().lower()\n        profile = profile_by_id(profile_id)\n        if not is_portfolio_connection_profile(profile):\n            raise ValueError(\n                f\"connection profile is not eligible for read-only portfolios: {profile_id}\"\n            )\n        label = str(raw.get(\"label\") or profile.label).strip()\n        if (\n            not label\n            or len(label) > 80\n            or any(ord(character) < 32 for character in label)\n        ):\n            raise ValueError(\n                \"connection label must contain 1 to 80 printable characters\"\n            )","sourceCodeStart":285,"sourceCodeEnd":321,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/trading/connections.py#L285-L321","documentation":"Raised while parsing persisted local-connection settings: an entry in the connections list is not a JSON object (e.g. it is a string, number, list, or null). _parse expects each serialized connection to be a dict with id/profile_id/label keys, so any other JSON value is rejected before field validation begins.","triggerScenarios":"Calling list() or save() on a store whose loaded settings contain a non-dict element in the connections array — e.g. [\"alpaca\", {...}], [null], or a bare string entry edited by hand.","commonSituations":"Hand-editing the connections settings file and accidentally leaving a stray string or comment-like entry; a partially written/corrupted settings file after a crash; migrating from an older format that allowed shorthands like plain connection names.","solutions":["Open the settings file and make every element of the connections array a JSON object with at minimum id and profile_id","Remove stray/legacy non-object entries, then re-add them properly via store.create()","If the file is corrupted, back it up and let the store recreate a fresh one","Validate the file with a JSON schema or json.load plus an isinstance(item, dict) check before handing it to the store"],"exampleFix":"// before\n{\"connections\": [\"alpaca\"]}\n\n// after\n{\"connections\": [{\"id\": \"alpaca\", \"profile_id\": \"paper\", \"label\": \"Alpaca paper\"}]}","handlingStrategy":"validation","validationCode":"import json\ndata = json.loads(path.read_text())\nentries = data.get(\"connections\", [])\nif not all(isinstance(e, dict) for e in entries):\n    raise ValueError(\"connections list contains non-object entries\")","typeGuard":"def is_connection_object(raw: object) -> bool:\n    return isinstance(raw, dict)","tryCatchPattern":"try:\n    store.list()\nexcept ValueError as exc:\n    if \"must be an object\" in str(exc):\n        # locate and fix/remove the offending entry, then retry\n        ...","preventionTips":["Only mutate connection settings through the store API, never a text editor","Lint settings files after manual edits with a small schema check","Back up settings before migrations that rewrite the connections array"],"tags":["python","json","settings-validation","configuration"],"backgroundTag":"schema-validation-failed","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}