langflow-ai/langflow · warning · SystemExit

No ``*.py`` files under {in_tree}; nothing to port.

Error message

No ``*.py`` files under {in_tree}; nothing to port.

What it means

After scanning the in-tree provider directory, port_bundle.py requires at least one porting unit: either a top-level *.py file or a nested subpackage. If the directory contains no Python files at all (only __pycache__, data files, or nothing), there is nothing to mechanically port and the script exits with 'No *.py files under <path>; nothing to port.'

Source

Thrown at scripts/migrate/port_bundle.py:735

            nested_subdirs.append(src)
            continue
        if not src.is_file() or src.suffix != ".py":
            continue
        text = src.read_text(encoding="utf-8")
        if "from langflow" in text:
            msg = (
                f"{src} imports from ``langflow`` -- the bundle is installed "
                "against the public BUNDLE_API surface (lfx), not Langflow "
                "internals.  Either rewrite the import or leave the component "
                "in-tree.  See src/bundles/PORTING.md § 0."
            )
            raise SystemExit(msg)
        classes = () if src.name == "__init__.py" else _discover_classes(text)
        component_files.append(ComponentFile(path=src, classes=classes))

    if not component_files and not nested_subdirs:
        msg = f"No ``*.py`` files under {in_tree}; nothing to port."
        raise SystemExit(msg)

    if migration_release is not None and not re.fullmatch(r"\d+\.\d+\.\d+", migration_release):
        msg = f"--migration-release {migration_release!r} must be a three-segment SemVer (e.g. 1.10.0)."
        raise SystemExit(msg)

    resolved_display = display_name if display_name is not None else bundle.replace("_", " ").title()

    shared_base = LFX_BASE / bundle
    shared_base_dir = shared_base if shared_base.is_dir() else None

    backend_test_dirs = _discover_backend_test_dirs(bundle)
    ruff_ignores = _discover_ruff_ignores(bundle)
    base_extra_present = _discover_base_extra(bundle)

    legacy_dynamic, legacy_all = _parse_legacy_init(in_tree / "__init__.py")

    consumer_rewrites: tuple[ConsumerRewrite, ...] = ()
    if discover_consumers:

View on GitHub (pinned to 976ec789d2)

Solutions

  1. List the directory shown in the error: `ls -la <in-tree path>` to confirm it is empty of *.py.
  2. If it is debris, delete the directory instead of porting it.
  3. If modules should exist, restore them from git (`git checkout <ref> -- <dir>`) and re-run.

Example fix

# before
ls src/lfx/src/lfx/components/legacy  # only __pycache__
python scripts/migrate/port_bundle.py --bundle legacy
# error: No ``*.py`` files under ...; nothing to port.

# after
git rm -r src/lfx/src/lfx/components/legacy  # remove debris instead of porting
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path

def has_portable_units(provider_dir: Path) -> bool:
    top = any(p.suffix == ".py" for p in provider_dir.iterdir())
    nested = any(p.is_dir() and p.name != "__pycache__" for p in provider_dir.iterdir())
    return top or nested

Prevention

When it happens

Trigger: Running port_bundle.py --bundle <name> on an emptied or never-populated provider directory — e.g. one whose modules were already deleted in a prior cleanup but whose folder remained.

Common situations: Leftover empty directories after a partial migration; placeholder provider dirs; files with wrong extensions (.py.txt) after a bad merge.

Related errors


AI-assisted analysis of langflow-ai/langflow@976ec789d2 (2026-08-14). Data as JSON: /api/errors/61763d54eb46d181. Report an issue: GitHub.