{"record":{"id":"2b999032c95d72df","repo":"langflow-ai/langflow","slug":"destination-already-exists-already-consolidated","errorCode":null,"errorMessage":"destination already exists (already consolidated?): {dst}","messagePattern":"destination already exists \\(already consolidated\\?\\): (.+?)","errorType":"console","errorClass":"SystemExit","httpStatus":null,"severity":"warning","filePath":"scripts/migrate/consolidate_bundles.py","lineNumber":283,"sourceCode":"    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\n    classes = discover_component_classes(src)\n    py_files = sorted(src.glob(\"*.py\"))\n    print(f\"  {provider}: {len(py_files)} file(s), {len(classes)} component class(es) -> {dst.relative_to(REPO_ROOT)}\")","sourceCodeStart":265,"sourceCodeEnd":301,"githubUrl":"https://github.com/langflow-ai/langflow/blob/976ec789d2886a86de109c044d089d68e96c9a35/scripts/migrate/consolidate_bundles.py#L265-L301","documentation":"The second guard in move_provider(): before touching anything it checks that the destination (BUNDLES_PKG / slug, where slug = provider.lower()) does not already exist. A pre-existing destination almost always means the provider was already consolidated, and proceeding would overwrite or interleave files. The script refuses with 'destination already exists (already consolidated?): <path>'.","triggerScenarios":"Re-running `python scripts/migrate/consolidate_bundles.py --apply <provider>` after a successful earlier run; running it twice in the same session; a provider whose lowercased slug collides with an already-ported bundle's slug.","commonSituations":"Retry after an interrupted bulk run where this provider had already completed; case-collision between providers that differ only in casing (slug is lowercased); forgetting that a previous dry-run with --apply had already moved this one.","solutions":["Confirm the provider is already consolidated: inspect the destination directory shown in the error — it should contain the moved modules plus the ext registration.","If truly duplicated/leftover, delete the destination bundle directory (and its registration) and re-run, or better, restore from git: `git checkout -- <dst>` then re-run.","For slug collisions between differently-cased providers, rename one bundle or port it manually via port_bundle.py with a distinct name."],"exampleFix":"# before\npython scripts/migrate/consolidate_bundles.py --apply openai  # second run\n# error: destination already exists (already consolidated?): src/bundles/lfx_bundles/openai\n\n# after\ngit status src/bundles/lfx_bundles/openai  # verify it is complete and committed, then skip the provider\npython scripts/migrate/consolidate_bundles.py --apply next_provider","handlingStrategy":"validation","validationCode":"from pathlib import Path\n\nBUNDLES_PKG = Path(\"src/bundles/lfx_bundles\")  # adjust to the path in the error\n\ndef already_consolidated(provider: str) -> bool:\n    return (BUNDLES_PKG / provider.lower()).exists()","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Make bulk consolidation scripts skip providers whose destination already exists instead of aborting the whole run.","Commit after each successful provider move so a re-run is detectable via git status.","The slug is provider.lower() — watch for casing collisions between providers."],"tags":["migration","idempotency","filesystem","cli"],"backgroundTag":null,"analyzedSha":"976ec789d2886a86de109c044d089d68e96c9a35","analyzedAt":"2026-08-14T18:23:12.227Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}