{"record":{"id":"4677efd49c5f0a17","repo":"langflow-ai/langflow","slug":"provider-directory-not-found-src","errorCode":null,"errorMessage":"provider directory not found: {src}","messagePattern":"provider directory not found: (.+?)","errorType":"console","errorClass":"SystemExit","httpStatus":null,"severity":"error","filePath":"scripts/migrate/consolidate_bundles.py","lineNumber":280,"sourceCode":"    \"\"\"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    \"\"\"\n    return provider.lower()\n\n\ndef move_provider(provider: str, *, apply: bool) -> list[tuple[str, str]]:\n    \"\"\"Move one provider into the metapackage and leave a shim. Returns its classes.\"\"\"\n    slug = bundle_slug(provider)\n    src = COMPONENTS_DIR / provider\n    dst = BUNDLES_PKG / slug\n    if not src.is_dir():\n        msg = f\"provider directory not found: {src}\"\n        raise SystemExit(msg)\n    if dst.exists():\n        msg = f\"destination already exists (already consolidated?): {dst}\"\n        raise SystemExit(msg)\n\n    # move_provider relocates only top-level ``*.py`` modules (see the glob\n    # below) but rmtree's the whole source tree.  A provider with a subpackage\n    # would have its subdir silently destroyed -- never copied to the bundle and\n    # never migration-mapped.  Refuse rather than half-move; port_bundle.py is\n    # the tool for nested layouts.\n    subdirs = sorted(p.name for p in src.iterdir() if p.is_dir() and p.name != \"__pycache__\")\n    if subdirs:\n        msg = (\n            f\"{provider}: source has subdirectory/ies {subdirs} that move_provider does not \"\n            \"relocate (it copies only top-level *.py modules). Use port_bundle.py, which \"\n            \"handles nested subpackages, instead.\"\n        )\n        raise SystemExit(msg)\n","sourceCodeStart":262,"sourceCodeEnd":298,"githubUrl":"https://github.com/langflow-ai/langflow/blob/976ec789d2886a86de109c044d089d68e96c9a35/scripts/migrate/consolidate_bundles.py#L262-L298","documentation":"consolidate_bundles.py's move_provider() relocates one provider folder from the in-tree components directory into the lfx-bundles metapackage. The first guard verifies the source directory (COMPONENTS_DIR / provider) exists; if it does not, the script aborts with 'provider directory not found: <abs path>' via SystemExit. The message includes the absolute path so you can see exactly which directory the script looked for.","triggerScenarios":"Running `python scripts/migrate/consolidate_bundles.py [--apply] <provider>` (or letting it iterate all PROVIDER_DEPS) where <provider> has no folder under the components dir — a typo in the provider name, a provider already moved in an earlier run, or running the script from a checkout where the tree layout changed.","commonSituations":"Typos or wrong casing ('OpenAI' vs 'openai' — the lookup is case-sensitive); re-running the consolidation after it partially completed; provider list in PROVIDER_DEPS drifting out of sync with the actual directories after a refactor.","solutions":["List the actual providers: `ls <COMPONENTS_DIR as shown in the error path>` and pass the exact directory name.","If the provider was already consolidated, check that the bundle exists under BUNDLES_PKG and skip it (or handle error 44's duplicate case).","If PROVIDER_DEPS contains a stale name, remove/update the entry in consolidate_bundles.py."],"exampleFix":"# before\npython scripts/migrate/consolidate_bundles.py --apply open_ai\n# error: provider directory not found: .../lfx/components/open_ai\n\n# after\npython scripts/migrate/consolidate_bundles.py --apply openai","handlingStrategy":"validation","validationCode":"from pathlib import Path\n\nCOMPONENTS_DIR = Path(\"src/lfx/src/lfx/components\")  # adjust to the value printed in the error\n\ndef provider_exists(provider: str) -> bool:\n    return (COMPONENTS_DIR / provider).is_dir()","typeGuard":null,"tryCatchPattern":"import subprocess, sys\n\ntry:\n    subprocess.run([sys.executable, \"scripts/migrate/consolidate_bundles.py\", \"--apply\", provider], check=True)\nexcept subprocess.CalledProcessError as exc:\n    # SystemExit(msg) -> non-zero exit with the diagnosis on stdout\n    if \"provider directory not found\" in (exc.stdout or \"\"):\n        print(f\"skip {provider}: not present in this tree\")\n    else:\n        raise","preventionTips":["Derive the provider list from actual directory names (iterdir) instead of a hardcoded list that can drift.","Do a dry run (no --apply) first — the guard fires before any mutation.","Names are case-sensitive directory lookups; always pass the exact folder name."],"tags":["migration","filesystem","cli","validation"],"backgroundTag":null,"analyzedSha":"976ec789d2886a86de109c044d089d68e96c9a35","analyzedAt":"2026-08-14T18:23:12.227Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}