{"record":{"id":"8ead02a118bd9694","repo":"infiniflow/ragflow","slug":"invalid-model-config-for-browser-llm-id-llm-id","errorCode":null,"errorMessage":"Invalid model config for Browser llm_id={llm_id}","messagePattern":"Invalid model config for Browser llm_id=(.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/component/browser.py","lineNumber":411,"sourceCode":"        if explicit:\n            return explicit\n\n        provider = self._infer_provider_name(cfg)\n        fallback = str(FACTORY_DEFAULT_BASE_URL.get(provider, \"\")).strip()\n        return fallback if fallback else \"\"\n\n    def _build_browser_llm(self):\n        from browser_use.llm import ChatBrowserUse, ChatOpenAI\n\n        chat_model_config = resolve_model_config(\n            self._canvas.get_tenant_id(),\n            resolve_model_type(self._canvas.get_tenant_id(), self._param.llm_id),\n            self._param.llm_id,\n        )\n        cfg = self._as_model_config_dict(chat_model_config)\n        model_name = self._normalize_model_name(cfg.get(\"model_name\") or cfg.get(\"model\") or self._param.llm_id)\n        if not model_name:\n            raise ValueError(f\"Invalid model config for Browser llm_id={self._param.llm_id}\")\n        base_url = self._resolve_openai_compatible_base_url(cfg)\n\n        # ChatBrowserUse only supports bu-* models. For tenant models, use OpenAI-compatible adapter.\n        if model_name.startswith(\"bu-\") or model_name.startswith(\"browser-use/\"):\n            llm_kwargs = {\n                \"model\": model_name,\n                \"api_key\": cfg.get(\"api_key\"),\n                \"base_url\": base_url,\n                \"temperature\": self._param.temperature,\n                \"max_retries\": self._param.max_retries,\n            }\n            llm_kwargs = {k: v for k, v in llm_kwargs.items() if v not in (None, \"\")}\n            return ChatBrowserUse(**llm_kwargs)\n\n        # browser-use Agent defaults to json_schema response_format and may use tool_choice via\n        # ChatDeepSeek. Many providers (e.g. DeepSeek thinking models) reject both. Use ChatOpenAI\n        # with schema-in-prompt and without forced structured output on the first run.\n        llm_kwargs = {","sourceCodeStart":393,"sourceCodeEnd":429,"githubUrl":"https://github.com/infiniflow/ragflow/blob/554fb1133ac3861732235ad9c377eb5e0a770665/agent/component/browser.py#L393-L429","documentation":"Raised in the Browser agent component's _build_browser_llm (agent/component/browser.py) when the tenant's resolved model configuration yields no usable model name: cfg has neither 'model_name' nor 'model', and self._param.llm_id is also empty/None after normalization. This means the component was configured with an LLM binding that is broken or empty, so no browser-use Chat model can be constructed.","triggerScenarios":"Adding a Browser component to an agent canvas and selecting an llm_id whose tenant model record is missing/deleted, or leaving llm_id empty when the model config lookup returns nothing; also when the model was removed from the tenant's provider settings but the canvas still references it. Fires when the component initializes its LLM at run time.","commonSituations":"Deleted or re-configured LLM providers leaving stale llm_id references in saved canvases; multi-tenant setups where the model belongs to another tenant; API keys rotated and the model row dropped; canvas JSON copied between environments without matching model setups.","solutions":["Open the Browser component in the agent editor and re-select a valid, currently configured LLM from the tenant's model list","Verify the model exists: check the tenant's LLM/provider settings page and that the llm_id referenced in the canvas JSON resolves to a row with a model name","If llm_id was left blank intentionally, pick a default model — the component requires one","After re-creating the model (e.g. re-adding the API key), re-select it in the component so a fresh llm_id is stored"],"exampleFix":"# before (canvas JSON)\n\"llm_id\": \"\"   # or a stale id of a deleted model\n\n# after\n\"llm_id\": \"<id-of-currently-configured-model@tenant>\"","handlingStrategy":"validation","validationCode":"from api.db.services.llm import LLMService  # conceptually\n\ndef resolve_browser_llm_id(tenant_id, llm_id):\n    if not llm_id:\n        raise ValueError('Browser component requires an llm_id')\n    # verify the model still exists for this tenant before running the canvas\n    exists, cfg = tenant_model_lookup(tenant_id, llm_id)\n    if not exists or not (cfg.get('model_name') or cfg.get('model')):\n        raise ValueError(f'llm_id {llm_id} has no resolvable model name; re-select the model')\n    return llm_id","typeGuard":"def has_resolvable_model_name(cfg: dict) -> bool:\n    return bool(cfg.get('model_name') or cfg.get('model'))","tryCatchPattern":"try:\n    component.run(...)\nexcept ValueError as e:\n    if 'Invalid model config for Browser' in str(e):\n        mark_component_needs_reconfig(component, 'Re-select the LLM in the Browser component')\n    else:\n        raise","preventionTips":["Re-select the Browser component's LLM after changing or deleting tenant models","Validate llm_id references when importing canvases across environments","Keep at least one working model configured per tenant that uses Browser components"],"tags":["agent-component","browser-use","llm-config","configuration"],"backgroundTag":null,"analyzedSha":"554fb1133ac3861732235ad9c377eb5e0a770665","analyzedAt":"2026-08-15T09:20:16.380Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}