langflow-ai/langflow · error · SystemExit
{src} imports from ``langflow`` -- the bundle is installed a
Error message
{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. What it means
Identical guard to error 54, but for top-level provider modules rather than nested subpackage files: port_bundle.py reads every top-level *.py under the in-tree provider dir and refuses the port if any contains 'from langflow'. Bundles are distributed standalone against lfx, so a Langflow-internal import makes the module unportable as-is; the error names the offending file and defers to PORTING.md § 0.
Source
Thrown at scripts/migrate/port_bundle.py:729
f"{nested} 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)
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)View on GitHub (pinned to 976ec789d2)
Solutions
- Rewrite the import in the named file to its lfx counterpart (e.g. langflow.custom -> lfx.custom, langflow.io -> lfx.io, langflow.schema -> lfx.schema).
- Grep the whole provider dir first: `grep -rn 'from langflow' <in-tree dir>` to fix all hits in one pass.
- Re-run the port; the guard re-checks every file each time.
Example fix
# before (openai/model.py) from langflow.io import Output, StrInput # after (openai/model.py) from lfx.io import Output, StrInput
Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
def top_level_langflow_imports(provider_dir: Path) -> list[Path]:
return [
p for p in sorted(provider_dir.glob("*.py"))
if "from langflow" in p.read_text(encoding="utf-8")
] Prevention
- grep -rn 'from langflow' <provider dir> and fix every hit (code, comments, docstrings) before porting.
- Map langflow.* imports to their lfx.* counterparts (custom, io, schema, logging) as part of pre-port cleanup.
When it happens
Trigger: Running port_bundle.py on a provider where a top-level module (e.g. <provider>/model.py) still does `from langflow.field_typing import ...` or any other langflow import. Like 54, the detection is a raw substring test on the file text.
Common situations: Pre-lfx-split component code; partially migrated providers where most files were converted but one was missed; false positives from comments containing the phrase.
Related errors
- {nested} imports from ``langflow`` -- the bundle is installe
- error: {source} entries field must be a list
- error: {source} ambiguous_bare_names field must be a list
- The '{provider}' components moved to the 'lfx-bundles' distr
- provider directory not found: {src}
AI-assisted analysis of langflow-ai/langflow@976ec789d2 (2026-08-14).
Data as JSON: /api/errors/b8a06caa3843fe51.
Report an issue: GitHub.