{"record":{"id":"e0fc6370fb5e2051","repo":"unclecode/crawl4ai","slug":"error-msg","errorCode":null,"errorMessage":"error_msg","messagePattern":"error_msg","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"deploy/docker/api.py","lineNumber":341,"sourceCode":"\nasync def handle_markdown_request(\n    url: str,\n    filter_type: FilterType,\n    query: Optional[str] = None,\n    cache: str = \"0\",\n    config: Optional[dict] = None,\n    provider: Optional[str] = None,\n    temperature: Optional[float] = None,\n    base_url: Optional[str] = None\n) -> str:\n    \"\"\"Handle markdown generation requests.\"\"\"\n    crawler = None\n    try:\n        # Validate provider if using LLM filter\n        if filter_type == FilterType.LLM:\n            is_valid, error_msg = validate_llm_provider(config, provider)\n            if not is_valid:\n                raise HTTPException(\n                    status_code=status.HTTP_400_BAD_REQUEST,\n                    detail=error_msg\n                )\n        decoded_url = unquote(url)\n        if not decoded_url.startswith(('http://', 'https://')) and not decoded_url.startswith((\"raw:\", \"raw://\")):\n            decoded_url = 'https://' + decoded_url\n        validate_url_destination(decoded_url)\n\n        if filter_type == FilterType.RAW:\n            md_generator = DefaultMarkdownGenerator()\n        else:\n            # Provider by name only; base_url/api_token are server-derived.\n            from llm_broker import resolve_llm\n            _llm = resolve_llm(config, provider)\n            content_filter = {\n                FilterType.FIT: PruningContentFilter(),\n                FilterType.BM25: BM25ContentFilter(user_query=query or \"\"),\n                FilterType.LLM: LLMContentFilter(","sourceCodeStart":323,"sourceCodeEnd":359,"githubUrl":"https://github.com/unclecode/crawl4ai/blob/7e801521428ee12509994d39151006f64055ebe3/deploy/docker/api.py#L323-L359","documentation":"HTTP 400 from the markdown endpoint (deploy/docker/api.py:341) when filter_type == LLM and validate_llm_provider(config, provider) rejects the provider configuration; detail is the validator's error_msg (e.g. provider not allow-listed or missing required config). Fast-path client validation before any crawling starts, so nothing is charged/crawled.","triggerScenarios":"GET/POST /md with filter=llm and a provider name absent from the server's configured LLM providers; provider configured but its required fields (api_token, base_url) missing server-side; case-mismatched provider strings.","commonSituations":"Same allow-list drift as 150 but on the markdown-generation route; server config trimmed for security and clients unaware of permitted providers.","solutions":["Read error_msg in the 400 detail — it states exactly what validation failed.","Use a provider name exactly matching the server's llm config section.","Fix server config (add provider with token/base_url) if that provider is intended to be offered.","Or switch filter_type to raw to bypass LLM filtering entirely."],"exampleFix":"# before\nr = requests.get(f\"{base}/md\", params={\"url\": u, \"f\": \"llm\", \"provider\": \"custom\"})\n\n# after\nr = requests.get(f\"{base}/md\", params={\"url\": u, \"f\": \"llm\", \"provider\": \"openai/gpt-4o-mini\"})\nif r.status_code == 400:\n    print(r.json()[\"detail\"])  # validator's reason","handlingStrategy":"validation","validationCode":"def llm_filter_request_valid(filter_type: str, provider: str | None) -> bool:\n    if filter_type != \"llm\":\n        return True\n    return provider is not None and provider in ALLOWED_PROVIDERS","typeGuard":"from enum import Enum\n\nclass FilterType(str, Enum):\n    RAW = \"raw\"\n    LLM = \"llm\"\n\ndef is_valid_filter_combo(f: str, provider: str | None) -> bool:\n    return (f == FilterType.RAW) or (f == FilterType.LLM and provider in ALLOWED_PROVIDERS)","tryCatchPattern":"r = await client.get(\"/md\", params=params)\nif r.status_code == 400:\n    params[\"f\"] = \"raw\"  # drop LLM filter, retry without\n    r = await client.get(\"/md\", params=params)","preventionTips":["Cache the server's allowed provider list and refresh it on deploy","Default to raw filter when provider config is uncertain"],"tags":["http-400","llm-provider","validation","markdown"],"backgroundTag":null,"analyzedSha":"7e801521428ee12509994d39151006f64055ebe3","analyzedAt":"2026-08-14T20:46:20.673Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}