{"record":{"id":"a572e5e4e087fee1","repo":"HKUDS/Vibe-Trading","slug":"path-must-start-with","errorCode":null,"errorMessage":"path must start with \"/\"","messagePattern":"path must start with \"/\"","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/channels/websocket.py","lineNumber":112,"sourceCode":"\n    @field_validator(\"unix_socket_path\")\n    @classmethod\n    def unix_socket_path_format(cls, value: str) -> str:\n        value = value.strip()\n        if not value:\n            return \"\"\n        if \"\\x00\" in value:\n            raise ValueError(\"unix_socket_path must not contain NUL bytes\")\n        path = Path(value).expanduser()\n        if not path.is_absolute():\n            raise ValueError(\"unix_socket_path must be an absolute path\")\n        return str(path)\n\n    @field_validator(\"path\")\n    @classmethod\n    def path_must_start_with_slash(cls, value: str) -> str:\n        if not value.startswith(\"/\"):\n            raise ValueError('path must start with \"/\"')\n        return _normalize_config_path(value)\n\n    @field_validator(\"token_issue_path\")\n    @classmethod\n    def token_issue_path_format(cls, value: str) -> str:\n        value = value.strip()\n        if not value:\n            return \"\"\n        if not value.startswith(\"/\"):\n            raise ValueError('token_issue_path must start with \"/\"')\n        return _normalize_config_path(value)\n\n    @model_validator(mode=\"after\")\n    def token_issue_path_differs_from_ws_path(self) -> Self:\n        if not self.token_issue_path:\n            return self\n        if _normalize_config_path(self.token_issue_path) == _normalize_config_path(self.path):\n            raise ValueError(\"token_issue_path must differ from path (the WebSocket upgrade path)\")","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/channels/websocket.py#L94-L130","documentation":"Raised by the WebSocketConfig field validator for path when the HTTP/WebSocket upgrade path does not start with '/'. URL paths must begin with a slash to be routable (e.g. '/ws'); the validator normalizes and stores the path via _normalize_config_path after this check.","triggerScenarios":"Setting path=\"ws\" or path=\"connect\" instead of \"/ws\" / \"/connect\" in the channel config. Any value whose first character is not '/' raises.","commonSituations":"YAML/JSON config copied from a client-side URL where the leading slash was dropped; building the path by concatenation like \"\" + endpoint; env var WEBSOCKET_PATH=ws without the slash; template interpolation omitting the leading '/'.","solutions":["Add the leading slash: path: /ws","If the value comes from an env var, update it to include the leading slash and audit other path-like settings in the same file","When concatenating paths programmatically, use '/' + endpoint.lstrip('/')"],"exampleFix":"# before\npath = \"ws\"\n# after\npath = \"/ws\"","handlingStrategy":"validation","validationCode":"ws_path = \"/\" + raw_path.lstrip(\"/\")  # normalize before config\nassert WebSocketConfig(path=ws_path)  # or: assert ws_path.startswith(\"/\")","typeGuard":"def is_valid_ws_path(p: str) -> bool:\n    return isinstance(p, str) and p.startswith(\"/\")","tryCatchPattern":null,"preventionTips":["Normalize paths with '/' + p.lstrip('/') when building programmatically","Include the leading slash in env var docs and examples","Lint YAML config for leading-slash conventions on all route fields"],"tags":["websocket","path-validation","config-validation"],"backgroundTag":"config-validation-failed","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}