{"record":{"id":"23c943d16622f3a8","repo":"HKUDS/Vibe-Trading","slug":"broker-must-not-be-blank-23c943","errorCode":null,"errorMessage":"broker must not be blank","messagePattern":"broker must not be blank","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/trading/service.py","lineNumber":1141,"sourceCode":"    key = str(broker or \"\").strip().lower()\n    if not key:\n        return None\n    for profile in list_profiles():\n        if profile.connector == key and profile_supports_live_runner(profile):\n            return profile\n    return None\n\n\ndef broker_supports_live_runner(broker: str) -> bool:\n    \"\"\"Return whether any configured profile exposes live runner management.\"\"\"\n    return live_runner_profile_for_broker(broker) is not None\n\n\ndef connector_profile_id_for_broker(broker: str) -> str:\n    \"\"\"Return the preferred connector profile id for a broker on-ramp.\"\"\"\n    key = str(broker or \"\").strip().lower()\n    if not key:\n        raise ValueError(\"broker must not be blank\")\n\n    candidates = [profile for profile in list_profiles() if profile.connector == key and profile.environment == \"live\"]\n    for profile in candidates:\n        if profile.transport == \"remote_mcp\":\n            return profile.id\n    if candidates:\n        return candidates[0].id\n    return f\"{key}-live-mcp\"\n\n\ndef runner_tool_name(connector: str, operation: str) -> str | None:\n    \"\"\"Map a runner operation to a connector-specific remote MCP tool name.\"\"\"\n    if connector == \"robinhood\":\n        from src.trading.connectors.robinhood.mcp import runner_tool_name as _runner_tool_name\n\n        return _runner_tool_name(operation)\n    return None\n","sourceCodeStart":1123,"sourceCodeEnd":1159,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/trading/service.py#L1123-L1159","documentation":"connector_profile_id_for_broker resolves the preferred connector profile id for a broker on-ramp. It normalizes the broker argument (strip + lower) and immediately rejects empty/whitespace-only/None input with ValueError('broker must not be blank'), since there is no meaningful profile lookup without a broker key.","triggerScenarios":"Calling connector_profile_id_for_broker('') , connector_profile_id_for_broker('   '), or connector_profile_id_for_broker(None) — e.g. live_authorize_endpoint forwarding an unvalidated request field or an unset config/env value.","commonSituations":"An API request body where the broker field is missing or blank, form input not validated upstream, environment variable for the broker not set, or a caller passing broker=None as a default.","solutions":["Pass a non-empty broker identifier such as 'alpaca' or 'ibkr'","Validate and normalize the broker field at the API boundary (request schema) before calling this function","Default missing broker values from config explicitly and fail with a user-facing validation message"],"exampleFix":"# before\nprofile_id = connector_profile_id_for_broker(request.broker)  # request.broker may be ''\n\n# after\nbroker = (request.broker or '').strip().lower()\nif not broker:\n    raise HTTPException(status_code=422, detail=\"broker is required\")\nprofile_id = connector_profile_id_for_broker(broker)","handlingStrategy":"validation","validationCode":"def normalize_broker(broker):\n    key = str(broker or \"\").strip().lower()\n    if not key:\n        raise ValueError(\"broker is required\")\n    return key\n\nprofile_id = connector_profile_id_for_broker(normalize_broker(request.broker))","typeGuard":"def is_valid_broker(broker) -> bool:\n    return bool(str(broker or \"\").strip())","tryCatchPattern":null,"preventionTips":["Make broker a required field in request schemas/pydantic models","Normalize user input (strip/lower) at the API edge before service calls","Add integration tests covering blank-broker requests"],"tags":["validation","trading","broker","blank-argument"],"backgroundTag":"missing-required-parameter","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}