{"record":{"id":"3497c3a7aeddb3a4","repo":"OpenBB-finance/OpenBB","slug":"subcategory-subcategory-not-found-in-category","errorCode":null,"errorMessage":"Subcategory '{subcategory}' not found in category '{category}'. Available subcategories: {', '.join(sorted(cat_data.keys()))}","messagePattern":"Subcategory '(.+?)' not found in category '(.+?)'\\. Available subcategories: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"openbb_platform/extensions/mcp_server/openbb_mcp_server/app/app.py","lineNumber":643,"sourceCode":"                    description=\"Optional subcategory to filter by. \"\n                    \"Use 'general' for tools directly under the category.\"\n                ),\n            ] = None,\n        ) -> list[ToolInfo]:\n            \"\"\"List tools in a specific category and subcategory.\"\"\"\n            cat_data = category_index.get_subcategories(category)\n\n            if cat_data is None:\n                available = list(category_index.get_categories().keys())\n                raise ValueError(\n                    f\"Category '{category}' not found. \"\n                    f\"Available categories: {', '.join(sorted(available))}\"\n                )\n\n            if subcategory:\n                names = category_index.get_subcategory_names(category, subcategory)\n                if not names:\n                    raise ValueError(\n                        f\"Subcategory '{subcategory}' not found in category '{category}'. \"\n                        f\"Available subcategories: {', '.join(sorted(cat_data.keys()))}\"\n                    )\n            else:\n                names = category_index.get_category_names(category)\n\n            # Resolve active state from FastMCP's live tool list\n            active_tools = await mcp.list_tools()\n            active_names = {t.name for t in active_tools}\n\n            # Build descriptions — use live tool object when available,\n            # fall back to cached short description from the index.\n            tool_map = {t.name: t for t in active_tools}\n            results: list[ToolInfo] = []\n            for name in sorted(names):\n                if name in tool_map:\n                    desc = _extract_brief_description(tool_map[name].description or \"\")\n                else:","sourceCodeStart":625,"sourceCodeEnd":661,"githubUrl":"https://github.com/OpenBB-finance/OpenBB/blob/3e071fcc2cd9f891cac6040ae60296dba76dab46/openbb_platform/extensions/mcp_server/openbb_mcp_server/app/app.py#L625-L661","documentation":"Raised by the OpenBB MCP server when a valid category is given but the subcategory filter does not exist under it. get_subcategory_names() returns an empty list for unknown subcategories, and the view raises with the sorted list of valid subcategories for that category. It is a pure input-validation error on the category/subcategory pair.","triggerScenarios":"Calling list_category_tools(category='economy', subcategory='gdp') when 'gdp' is not a subcategory key under economy; using 'general' when the category has no direct tools; typos or renamed subcategories after an OpenBB upgrade.","commonSituations":"Clients guessing subcategory names from endpoint paths; extension version drift renaming router children; omitting subcategory vs using 'general' incorrectly.","solutions":["Use the subcategory names printed in the error's 'Available subcategories' list, exactly as shown.","Call the category listing without subcategory first to inspect the hierarchy.","Pass subcategory='general' only when you want tools directly under the category (as documented on the parameter).","Update the openbb extensions so subcategory names match what your client expects."],"exampleFix":"# before\ntools = await list_category_tools(category=\"economy\", subcategory=\"GDP\")\n\n# after\ntools = await list_category_tools(category=\"economy\", subcategory=\"gdp\")  # exact key from error listing","handlingStrategy":"validation","validationCode":"async def valid_subcategory(mcp_client, category: str, subcategory: str) -> bool:\n    result = await mcp_client.call_tool(\"list_category_tools\", {\"category\": category})\n    subcats = set(result.result.get(\"subcategories\", {}))\n    return subcategory in subcats or subcategory == \"general\"","typeGuard":"def is_valid_subcategory(sub: str, cat_data: dict) -> bool:\n    return isinstance(sub, str) and (sub in cat_data or sub == \"general\")","tryCatchPattern":"try:\n    tools = await list_category_tools(category=cat, subcategory=sub)\nexcept ValueError as e:\n    if \"Available subcategories:\" in str(e):\n        sub = str(e).split(\"Available subcategories:\")[-1].strip().split(\",\")[0].strip(\" '[]\")\n        tools = await list_category_tools(category=cat, subcategory=sub)\n    else:\n        raise","preventionTips":["Discover the subcategory hierarchy with a listing call before filtering.","Treat category/subcategory keys as opaque API identifiers — copy them exactly.","Re-validate hardcoded names whenever OpenBB extensions are upgraded."],"tags":["openbb","mcp","mcp-server","validation"],"backgroundTag":null,"analyzedSha":"3e071fcc2cd9f891cac6040ae60296dba76dab46","analyzedAt":"2026-08-14T23:40:48.960Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}