{"record":{"id":"eab0d3d17dbff396","repo":"OpenBB-finance/OpenBB","slug":"invalid-command-route-route","errorCode":null,"errorMessage":"Invalid command : route={route}","messagePattern":"Invalid command : route=(.+?)","errorType":"exception","errorClass":"AttributeError","httpStatus":null,"severity":"error","filePath":"openbb_platform/core/openbb_core/app/command_runner.py","lineNumber":454,"sourceCode":"        **kwargs,\n    ) -> OBBject:\n        \"\"\"Run a command and return the OBBject as output.\"\"\"\n        timestamp = datetime.now()\n        start_ns = perf_counter_ns()\n\n        command_map = execution_context.command_map\n        route = execution_context.route\n\n        if func := command_map.get_command(route=route):\n            obbject = await cls._execute_func(\n                route=route,\n                args=args,  # type: ignore\n                execution_context=execution_context,\n                func=func,\n                kwargs=kwargs,\n            )\n        else:\n            raise AttributeError(f\"Invalid command : route={route}\")\n\n        duration = perf_counter_ns() - start_ns\n\n        if execution_context.user_settings.preferences.metadata and isinstance(\n            obbject, OBBject\n        ):\n            try:\n                obbject.extra[\"metadata\"] = Metadata(\n                    arguments=kwargs,\n                    duration=duration,\n                    route=route,\n                    timestamp=timestamp,\n                )\n            except Exception as e:\n                if Env().DEBUG_MODE:\n                    raise OpenBBError(e) from e\n                warn(str(e), OpenBBWarning)\n","sourceCodeStart":436,"sourceCodeEnd":472,"githubUrl":"https://github.com/OpenBB-finance/OpenBB/blob/3e071fcc2cd9f891cac6040ae60296dba76dab46/openbb_platform/core/openbb_core/app/command_runner.py#L436-L472","documentation":"Raised by the DOT country/counterpart validator when the token list contains more than one entry and any entry (after strip/lower) is 'all' or '*'. The IMF API treats '*' as a standalone wildcard dimension; mixing it with explicit codes is not expressible, so the validator rejects it upfront.","triggerScenarios":"`country='USA,all'`, `counterpart='*,DEU'`, or appending 'all' to a code list dynamically, e.g. `','.join(codes + ['all'])` when codes is non-empty. A single 'all' or '*' alone is fine.","commonSituations":"UIs that add a default 'All' option to a multi-select that already has selections; string-building code that always appends a wildcard 'for completeness'; copy-pasting a defaults string that includes 'all' plus explicit codes.","solutions":["Use either a wildcard alone (`country='all'`) or explicit codes only (`country='USA,DEU'`) — never both.","In dynamic list building, drop 'all'/'*' tokens whenever the list has other entries (or short-circuit to just 'all').","Normalize case and whitespace before joining; the validator strips tokens, but your builder may not."],"exampleFix":"# before\ncodes = ['USA', 'DEU']\ncodes.append('all')\nres = obb.economy.direction_of_trade(provider='imf', country=','.join(codes), counterpart='W00')\n\n# after\ncodes = ['USA', 'DEU']\nres = obb.economy.direction_of_trade(provider='imf', country=','.join(codes), counterpart='W00')","handlingStrategy":"validation","validationCode":"def normalize_dot_codes(codes: list[str]) -> str:\n    stripped = [c.strip() for c in codes if c.strip()]\n    if not stripped:\n        raise ValueError('At least one country/counterpart code is required.')\n    if any(c.lower() in ('all', '*') for c in stripped):\n        if len(stripped) > 1:\n            raise ValueError(\"'all'/'*' must be used alone, not mixed with explicit codes.\")\n        return '*'\n    return ','.join(stripped)\n\ncountry = normalize_dot_codes(['USA', 'DEU'])","typeGuard":"def is_clean_code_list(codes: list[str]) -> bool:\n    s = [c.strip() for c in codes if c.strip()]\n    wildcards = [c for c in s if c.lower() in ('all', '*')]\n    return not wildcards or len(s) == 1","tryCatchPattern":null,"preventionTips":["Never build code lists by appending 'all' — short-circuit to 'all' alone when a wildcard is wanted.","In multi-select UIs, clear other selections when the user picks 'All'."],"tags":["imf","openbb","direction-of-trade","validation","wildcard","pydantic"],"backgroundTag":null,"analyzedSha":"3e071fcc2cd9f891cac6040ae60296dba76dab46","analyzedAt":"2026-08-14T23:40:48.960Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}