{"record":{"id":"45e85e23a5111c57","repo":"langflow-ai/langflow","slug":"the-provider-components-moved-to-the-lfx-bund","errorCode":null,"errorMessage":"The '{provider}' components moved to the 'lfx-bundles' distribution. Install it with:  pip install lfx-bundles   (or 'pip install langflow', which bundles it).","messagePattern":"The '(.+?)' components moved to the 'lfx-bundles' distribution\\. Install it with:  pip install lfx-bundles   \\(or 'pip install langflow', which bundles it\\)\\.","errorType":"exception","errorClass":"ModuleNotFoundError","httpStatus":null,"severity":"error","filePath":"scripts/migrate/consolidate_bundles.py","lineNumber":251,"sourceCode":"        \"\\n\"\n        \"This module re-points to the installed bundle distribution. It contains\\n\"\n        \"no component implementations and no third-party dependencies, and is\\n\"\n        \"removed once the deprecation window closes (M4).\\n\"\n        '\"\"\"\\n'\n        \"\\n\"\n        \"import importlib\\n\"\n        \"import sys\\n\"\n        \"\\n\"\n        \"try:\\n\"\n        f'    sys.modules[__name__] = importlib.import_module(\"lfx_bundles.{slug}\")\\n'\n        \"except ModuleNotFoundError as exc:\\n\"\n        '    if exc.name is not None and (exc.name == \"lfx_bundles\" or exc.name.startswith(\"lfx_bundles.\")):\\n'\n        \"        msg = (\\n\"\n        f\"            \\\"The '{provider}' components moved to the 'lfx-bundles' distribution. \\\"\\n\"\n        '            \"Install it with:  pip install lfx-bundles   \"\\n'\n        \"            \\\"(or 'pip install langflow', which bundles it).\\\"\\n\"\n        \"        )\\n\"\n        '        raise ModuleNotFoundError(msg, name=\"lfx_bundles\") from exc\\n'\n        \"    raise\\n\"\n    )\n\n\ndef _rewrite_self_imports(text: str, provider: str, slug: str) -> str:\n    \"\"\"Rewrite absolute ``lfx.components.<provider>`` self-refs to ``lfx_bundles.<slug>``.\"\"\"\n    return re.sub(rf\"\\blfx\\.components\\.{re.escape(provider)}\\b\", f\"lfx_bundles.{slug}\", text)\n\n\ndef bundle_slug(provider: str) -> str:\n    \"\"\"Bundle directory / ext-slug name for a provider.\n\n    Bundle names must satisfy ``BUNDLE_NAME_RE`` (lowercase), so the in-tree\n    source dir name is lowercased -- e.g. ``FAISS`` -> ``faiss``, ``Notion`` ->\n    ``notion``. Already-lowercase providers are unchanged. The historical\n    ``lfx.components.<provider>`` import paths (migration table) keep the\n    original casing; only the bundle dir + ``ext:<slug>`` id are lowercased.\n    \"\"\"","sourceCodeStart":233,"sourceCodeEnd":269,"githubUrl":"https://github.com/langflow-ai/langflow/blob/976ec789d2886a86de109c044d089d68e96c9a35/scripts/migrate/consolidate_bundles.py#L233-L269","documentation":"This message is not raised by the migration script itself — consolidate_bundles.py embeds it inside a generated shim module. When a provider directory (e.g. lfx/components/<provider>) is consolidated into the lfx-bundles metapackage, the old package path is left as a shim whose __init__.py re-exports from lfx_bundles.<slug>. If lfx-bundles (or langflow, which bundles it) is not installed, importing the old path raises ModuleNotFoundError with exactly this instruction text. It is a deliberate, actionable replacement for a bare 'No module named lfx_bundles'.","triggerScenarios":"In an environment with only `lfx` installed (not `langflow` and not `lfx-bundles`), executing `import lfx.components.openai` (or any import of the legacy module path for a consolidated provider), or loading a saved flow that references the legacy import path while lfx_bundles is missing. The shim catches the inner ModuleNotFoundError for lfx_bundles[.] and re-raises with this message; any other missing module propagates unchanged.","commonSituations":"Partial environments: installing bare `lfx` to get the executor CLI but old code/flows still import `lfx.components.<provider>`; CI images trimmed to lfx-only; a venv created before the bundles split, after which a `pip install -U lfx` no longer pulls the components.","solutions":["Install the metapackage: `pip install lfx-bundles`.","Or install the full distribution that depends on it: `pip install langflow`.","Longer term, migrate imports to the canonical bundle paths (lfx_bundles.<slug>, or the ext:<slug>:<Class> component ids) so code no longer depends on the legacy shim.","Verify with `python -c \"import lfx_bundles; print(lfx_bundles.__version__)\"` before re-running your app."],"exampleFix":"# before\npip install lfx\npython -c \"import lfx.components.openai\"  # ModuleNotFoundError: The 'openai' components moved ...\n\n# after\npip install lfx-bundles   # or: pip install langflow\npython -c \"import lfx.components.openai\"  # OK via shim","handlingStrategy":"validation","validationCode":"import importlib.util\n\nif importlib.util.find_spec(\"lfx_bundles\") is None:\n    raise SystemExit(\n        \"This flow needs consolidated components. Install first: pip install lfx-bundles (or pip install langflow)\"\n    )\n\nimport lfx.components.openai  # now safe","typeGuard":"import importlib.util\n\ndef legacy_provider_available(provider: str) -> bool:\n    \"\"\"True when the shim target lfx_bundles (or langflow) is importable.\"\"\"\n    return importlib.util.find_spec(\"lfx_bundles\") is not None or importlib.util.find_spec(\"langflow\") is not None","tryCatchPattern":"try:\n    import lfx.components.openai as openai_components\nexcept ModuleNotFoundError as exc:\n    if \"lfx-bundles\" in str(exc):\n        # actionable guidance, not a bare traceback\n        raise SystemExit(\n            \"Consolidated provider imported without its bundle. \"\n            \"Fix: pip install lfx-bundles\"\n        ) from exc\n    raise","preventionTips":["Pin 'lfx-bundles' (or 'langflow') in requirements whenever code imports any lfx.components.<provider> legacy path.","Prefer the canonical lfx_bundles.<slug> / ext:<slug> imports in new code so shims are irrelevant.","Smoke-test `import lfx.components.<provider>` in CI for every provider your flows reference."],"tags":["import","packaging","migration","module-not-found"],"backgroundTag":null,"analyzedSha":"976ec789d2886a86de109c044d089d68e96c9a35","analyzedAt":"2026-08-14T18:23:12.227Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}