langflow-ai/langflow · error · SystemExit
{provider}: source has subdirectory/ies {subdirs} that move_
Error message
{provider}: source has subdirectory/ies {subdirs} that move_provider does not relocate (it copies only top-level *.py modules). Use port_bundle.py, which handles nested subpackages, instead. What it means
move_provider() copies only top-level *.py modules but rmtree's the entire source tree afterwards. If the provider directory contained real subpackages (anything except __pycache__), those subdirectories would be silently destroyed — never copied to the bundle and never added to the migration mapping. To prevent that data loss, the script detects subdirectories and hard-fails, directing you to port_bundle.py, which handles nested subpackage layouts (e.g. agentics/helpers) correctly.
Source
Thrown at scripts/migrate/consolidate_bundles.py:297
msg = f"provider directory not found: {src}"
raise SystemExit(msg)
if dst.exists():
msg = f"destination already exists (already consolidated?): {dst}"
raise SystemExit(msg)
# move_provider relocates only top-level ``*.py`` modules (see the glob
# below) but rmtree's the whole source tree. A provider with a subpackage
# would have its subdir silently destroyed -- never copied to the bundle and
# never migration-mapped. Refuse rather than half-move; port_bundle.py is
# the tool for nested layouts.
subdirs = sorted(p.name for p in src.iterdir() if p.is_dir() and p.name != "__pycache__")
if subdirs:
msg = (
f"{provider}: source has subdirectory/ies {subdirs} that move_provider does not "
"relocate (it copies only top-level *.py modules). Use port_bundle.py, which "
"handles nested subpackages, instead."
)
raise SystemExit(msg)
classes = discover_component_classes(src)
py_files = sorted(src.glob("*.py"))
print(f" {provider}: {len(py_files)} file(s), {len(classes)} component class(es) -> {dst.relative_to(REPO_ROOT)}")
for module_stem, class_name in classes:
print(f" {module_stem}.{class_name} -> ext:{slug}:{class_name}@official")
if not apply:
return classes
dst.mkdir(parents=True)
for py in py_files:
content = _rewrite_self_imports(py.read_text(encoding="utf-8"), provider, slug)
(dst / py.name).write_text(content, encoding="utf-8")
# Remove the moved source, then replace the in-tree dir with a one-file shim.
shutil.rmtree(src)
src.mkdir()
(src / "__init__.py").write_text(_shim_source(provider, slug), encoding="utf-8")View on GitHub (pinned to 976ec789d2)
Solutions
- Use the correct tool: `python scripts/migrate/port_bundle.py --bundle <provider>` which ports nested subpackages wholesale.
- If the subdirectory is junk (scratch code, __pycache__ variants), delete or relocate it first, then re-run consolidate_bundles.py.
- If the subpackage is legitimately a separate concern, split it out before consolidating the flat remainder.
Example fix
# before python scripts/migrate/consolidate_bundles.py --apply agentics # error: agentics: source has subdirectory/ies ['helpers'] ... # after python scripts/migrate/port_bundle.py --bundle agentics --apply
Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
def is_flat_provider(src: Path) -> bool:
"""consolidate_bundles.move_provider only handles flat layouts."""
return not any(p.is_dir() and p.name != "__pycache__" for p in src.iterdir()) Prevention
- Check for subpackages before choosing the tool: flat -> consolidate_bundles.py, nested -> port_bundle.py.
- Never bypass this guard by deleting subdirectories to force the mechanical move — port them instead.
- The guard exists because the move rmtree's the source; ignoring it loses the subpackage permanently.
When it happens
Trigger: Running consolidate_bundles.py (dry-run or --apply) on a provider whose directory under COMPONENTS_DIR contains at least one subdirectory other than __pycache__. The guard fires before any mutation, so even a dry-run listing triggers it.
Common situations: Providers that grew helper subpackages over time; leftover experiment folders inside a provider dir; running the mechanical consolidation tool on a layout it was never designed for.
Related errors
- The '{provider}' components moved to the 'lfx-bundles' distr
- provider directory not found: {src}
- destination already exists (already consolidated?): {dst}
- Could not read lfx version from src/lfx/pyproject.toml
- --bundle {bundle!r} is not a valid bundle name (lowercase sn
AI-assisted analysis of langflow-ai/langflow@976ec789d2 (2026-08-14).
Data as JSON: /api/errors/dc8ee3591cbdf6f0.
Report an issue: GitHub.