{"record":{"id":"5472ca6d75806be8","repo":"browser-use/browser-use","slug":"module-name-has-no-attribute-name","errorCode":null,"errorMessage":"module '{__name__}' has no attribute '{name}'","messagePattern":"module '(.+?)' has no attribute '(.+?)'","errorType":"exception","errorClass":"AttributeError","httpStatus":null,"severity":"error","filePath":"browser_use/__init__.py","lineNumber":135,"sourceCode":"\t\"\"\"Lazy import mechanism - only import modules when they're actually accessed.\"\"\"\n\tif name in _LAZY_IMPORTS:\n\t\tmodule_path, attr_name = _LAZY_IMPORTS[name]\n\t\ttry:\n\t\t\tfrom importlib import import_module\n\n\t\t\tmodule = import_module(module_path)\n\t\t\tif attr_name is None:\n\t\t\t\t# For modules like 'models', return the module itself\n\t\t\t\tattr = module\n\t\t\telse:\n\t\t\t\tattr = getattr(module, attr_name)\n\t\t\t# Cache the imported attribute in the module's globals\n\t\t\tglobals()[name] = attr\n\t\t\treturn attr\n\t\texcept ImportError as e:\n\t\t\traise ImportError(f'Failed to import {name} from {module_path}: {e}') from e\n\n\traise AttributeError(f\"module '{__name__}' has no attribute '{name}'\")\n\n\n__all__ = [\n\t'Agent',\n\t'BrowserSession',\n\t'Browser',  # Alias for BrowserSession\n\t'BrowserProfile',\n\t'Controller',\n\t'DomService',\n\t'SystemPrompt',\n\t'ActionResult',\n\t'ActionModel',\n\t'AgentHistoryList',\n\t# Chat models\n\t'ChatOpenAI',\n\t'ChatGoogle',\n\t'ChatAnthropic',\n\t'ChatAnthropicBedrock',","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/browser-use/browser-use/blob/6c73fced2f6d45a11d88622fe56365a5fe18f28b/browser_use/__init__.py#L117-L153","documentation":"The dynamic extraction-schema compiler (used by the `extract` tool to turn a JSON Schema into a Pydantic model) only supports a structural subset of JSON Schema. `_check_unsupported` rejects composition/reference keywords listed in _UNSUPPORTED_KEYWORDS ($ref, allOf, anyOf, oneOf, not, etc.) because there is no reliable translation to a flat create_model field map. The error is raised at schema-compile time, before any LLM call or page extraction happens.","triggerScenarios":"Passing an `output_model_schema` / extraction schema that contains any of the unsupported keywords at the top level or in any nested node (e.g. {\"type\":\"object\",\"properties\":{\"x\":{\"anyOf\":[{\"type\":\"string\"},{\"type\":\"null\"}]}}} or a $ref to a shared definition). Also triggered by OpenAPI-derived schemas that ubiquitously use $ref/anyOf.","commonSituations":"Copying a schema from an OpenAPI spec or JSON-Schema-2020-12 source into extract(); modeling optional fields with anyOf [T, null] instead of type arrays; trying to reuse definitions via $defs/$ref for DRY schemas.","solutions":["Flatten the schema by hand: inline every $ref, and replace anyOf/oneOf/allOf unions with a single concrete type or a type array like {\"type\": [\"string\", \"null\"]} if supported by your version.","Replace optional-union patterns with the property flagged in `required` omission plus a nullable type representation the compiler accepts.","Keep extraction schemas small and hand-written for this tool — a flat object of scalar/array/object properties with enums as string enums.","If you need full JSON Schema unions, define a static Pydantic model and pass that instead of a raw schema where the API allows it."],"exampleFix":"# before\nschema = {\n  \"type\": \"object\",\n  \"properties\": {\n    \"price\": {\"anyOf\": [{\"type\": \"number\"}, {\"type\": \"null\"}]},\n    \"address\": {\"$ref\": \"#/$defs/address\"}\n  }\n}\n\n# after\nschema = {\n  \"type\": \"object\",\n  \"properties\": {\n    \"price\": {\"type\": \"number\"},\n    \"address\": {\"type\": \"object\", \"properties\": {\"city\": {\"type\": \"string\"}, \"zip\": {\"type\": \"string\"}}}\n  }\n}","handlingStrategy":"validation","validationCode":"UNSUPPORTED = {'$ref', '$defs', 'allOf', 'anyOf', 'oneOf', 'not'}\n\ndef schema_is_supported(node: dict) -> bool:\n    if not isinstance(node, dict):\n        return True\n    if any(kw in node for kw in UNSUPPORTED):\n        return False\n    return all(schema_is_supported(v) for v in node.get('properties', {}).values())","typeGuard":"def is_flat_extraction_schema(schema: dict) -> bool:\n    return (\n        isinstance(schema, dict)\n        and schema.get('type') == 'object'\n        and bool(schema.get('properties'))\n        and schema_is_supported(schema)\n    )","tryCatchPattern":"from browser_use.tools.extraction.schema_utils import schema_to_model\ntry:\n    model = schema_to_model(schema)\nexcept ValueError as e:\n    if 'Unsupported JSON Schema keyword' in str(e):\n        schema = flatten_refs_and_unions(schema)  # your normalizer\n        model = schema_to_model(schema)","preventionTips":["Hand-write extraction schemas instead of copying from OpenAPI specs.","Derefence $refs and inline unions with a preprocessing step before passing schemas to extract.","Add a unit test that compiles every schema your app uses with schema_to_model at import time."],"tags":["json-schema","extraction","validation","browser-use"],"backgroundTag":null,"analyzedSha":"6c73fced2f6d45a11d88622fe56365a5fe18f28b","analyzedAt":"2026-08-14T19:42:40.557Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}