{"record":{"id":"1b89d16bc9719629","repo":"OpenBB-finance/OpenBB","slug":"methods-must-be-a-list-of-strings","errorCode":null,"errorMessage":"methods must be a list of strings","messagePattern":"methods must be a list of strings","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"openbb_platform/extensions/mcp_server/openbb_mcp_server/models/mcp_config.py","lineNumber":175,"sourceCode":"        default_factory=list, description=\"Prompt configurations for this route.\"\n    )\n    exclude_args: list[str] | None = Field(\n        default=None, description=\"List of argument names to exclude from this route.\"\n    )\n\n    @field_validator(\"methods\", mode=\"before\")\n    @classmethod\n    def validate_methods(cls, v: str | list[str] | None) -> list[HTTPMethod] | None:\n        \"\"\"Normalize and validate HTTP methods.\"\"\"\n        if v is None:\n            return None\n\n        # Handle single string\n        if isinstance(v, str):\n            v = [v]\n\n        if not isinstance(v, list):\n            raise ValueError(\"methods must be a list of strings\")\n\n        # If '*' is present, it should be the only method\n        if \"*\" in v and len(v) > 1:\n            raise ValueError(\"Method '*' cannot be mixed with other HTTP methods.\")\n\n        # Validate each method\n        validated_methods = []\n        for method in v:\n            method_str = str(method).upper().strip() if method != \"*\" else \"*\"\n            try:\n                validated_methods.append(HTTPMethod(method_str))\n            except ValueError as exc:\n                valid_methods = [m.value for m in HTTPMethod]\n                raise ValueError(\n                    f\"Invalid HTTP method '{method}'. Valid methods: {', '.join(valid_methods)}\"\n                ) from exc\n\n        # Remove duplicates while preserving order","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/OpenBB-finance/OpenBB/blob/3e071fcc2cd9f891cac6040ae60296dba76dab46/openbb_platform/extensions/mcp_server/openbb_mcp_server/models/mcp_config.py#L157-L193","documentation":"Raised by the mode='before' validator for the 'methods' field of the MCP HTTP route config. The validator first coerces a single string into a one-element list; anything that is still not a list afterwards (int, dict, tuple, None-like objects, nested lists) is rejected with this message. It wraps into a pydantic ValidationError at config parse time.","triggerScenarios":"Passing methods=123, methods={\"GET\": True}, or methods=(\"GET\", \"POST\") (a tuple, not a list) in the mcp_config block; a JSON config that has \"methods\": \"object\" or a YAML mapping instead of a sequence. Note a plain string like \"GET\" is accepted and normalized to [\"GET\"].","commonSituations":"YAML indentation mistakes turning a list into a mapping, programmatic config builders emitting sets/tuples instead of lists, JSON configs authored by hand where methods is a dict of method->bool.","solutions":["Change the value to a list of strings: \"methods\": [\"GET\", \"POST\"] or a single string \"methods\": \"GET\"","If generating config programmatically, coerce with list(value) and ensure each element is a string","Check YAML/JSON syntax around the methods key (a stray mapping or scalar where a sequence is expected)"],"exampleFix":"# before\nopenapi_extra={\"mcp_config\": {\"methods\": {\"GET\": True}}}\n\n# after\nopenapi_extra={\"mcp_config\": {\"methods\": [\"GET\"]}}","handlingStrategy":"validation","validationCode":"m = cfg.get(\"methods\")\nif isinstance(m, str):\n    cfg[\"methods\"] = [m]\nelif not isinstance(m, list) or not all(isinstance(x, str) for x in m):\n    raise ValueError(\"methods must be a str or list[str]\")","typeGuard":"def is_valid_methods(v: object) -> bool:\n    if isinstance(v, str):\n        return True\n    return isinstance(v, list) and all(isinstance(x, str) for x in v)","tryCatchPattern":"try:\n    model = validate_mcp_config(cfg)\nexcept ValidationError as e:\n    if \"methods must be a list\" in str(e):\n        cfg[\"methods\"] = [str(x) for x in cfg[\"methods\"]]  # or fix the source\n        model = validate_mcp_config(cfg)\n    else:\n        raise","preventionTips":["Normalize methods to list[str] (accepting a single string) in your config loader","Validate generated configs with a JSON schema that types methods as array of strings","Watch YAML: a mapping under 'methods' instead of a sequence is the most common cause"],"tags":["pydantic","validation","mcp","http","config"],"backgroundTag":null,"analyzedSha":"3e071fcc2cd9f891cac6040ae60296dba76dab46","analyzedAt":"2026-08-14T23:40:48.960Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}