{"record":{"id":"52e88ff9c1476ec8","repo":"langflow-ai/langflow","slug":"migration-release-migration-release-r-must-be","errorCode":null,"errorMessage":"--migration-release {migration_release!r} must be a three-segment SemVer (e.g. 1.10.0).","messagePattern":"--migration-release (.+?) must be a three-segment SemVer \\(e\\.g\\. 1\\.10\\.0\\)\\.","errorType":"console","errorClass":"SystemExit","httpStatus":null,"severity":"error","filePath":"scripts/migrate/port_bundle.py","lineNumber":739,"sourceCode":"        text = src.read_text(encoding=\"utf-8\")\n        if \"from langflow\" in text:\n            msg = (\n                f\"{src} imports from ``langflow`` -- the bundle is installed \"\n                \"against the public BUNDLE_API surface (lfx), not Langflow \"\n                \"internals.  Either rewrite the import or leave the component \"\n                \"in-tree.  See src/bundles/PORTING.md § 0.\"\n            )\n            raise SystemExit(msg)\n        classes = () if src.name == \"__init__.py\" else _discover_classes(text)\n        component_files.append(ComponentFile(path=src, classes=classes))\n\n    if not component_files and not nested_subdirs:\n        msg = f\"No ``*.py`` files under {in_tree}; nothing to port.\"\n        raise SystemExit(msg)\n\n    if migration_release is not None and not re.fullmatch(r\"\\d+\\.\\d+\\.\\d+\", migration_release):\n        msg = f\"--migration-release {migration_release!r} must be a three-segment SemVer (e.g. 1.10.0).\"\n        raise SystemExit(msg)\n\n    resolved_display = display_name if display_name is not None else bundle.replace(\"_\", \" \").title()\n\n    shared_base = LFX_BASE / bundle\n    shared_base_dir = shared_base if shared_base.is_dir() else None\n\n    backend_test_dirs = _discover_backend_test_dirs(bundle)\n    ruff_ignores = _discover_ruff_ignores(bundle)\n    base_extra_present = _discover_base_extra(bundle)\n\n    legacy_dynamic, legacy_all = _parse_legacy_init(in_tree / \"__init__.py\")\n\n    consumer_rewrites: tuple[ConsumerRewrite, ...] = ()\n    if discover_consumers:\n        consumer_rewrites = _discover_external_consumers(bundle, in_tree, bundle_dir, shared_base_dir=shared_base_dir)\n\n    return PortPlan(\n        bundle=bundle,","sourceCodeStart":721,"sourceCodeEnd":757,"githubUrl":"https://github.com/langflow-ai/langflow/blob/976ec789d2886a86de109c044d089d68e96c9a35/scripts/migrate/port_bundle.py#L721-L757","documentation":"port_bundle.py accepts an optional --migration-release flag used to tag the migration mapping entries with the release in which the component moves out of tree. The value must be an exact three-segment SemVer (\\d+\\.\\d+\\.\\d+); anything else — '1.10', 'v1.10.0', '1.10.0-rc1', 'latest' — fails the fullmatch and aborts with this message before planning.","triggerScenarios":"Running `python scripts/migrate/port_bundle.py --bundle <name> --migration-release 1.10` or any non-three-numeric-segment value. Pre-release suffixes are rejected because the field feeds tooling that compares plain SemVer triples.","commonSituations":"Passing a two-segment minor version; copying a tag like 'v1.10.0' with the leading 'v'; pasting a full dev version from pyproject (e.g. 1.10.0.dev3).","solutions":["Pass exactly three dot-separated numbers: `--migration-release 1.10.0`.","Strip any 'v' prefix or pre-release suffix from the value you copied.","If unsure which release to record, check recent migration entries in migration_table.json for the convention."],"exampleFix":"# before\npython scripts/migrate/port_bundle.py --bundle openai --migration-release v1.10.0-rc1\n# error: --migration-release 'v1.10.0-rc1' must be a three-segment SemVer (e.g. 1.10.0).\n\n# after\npython scripts/migrate/port_bundle.py --bundle openai --migration-release 1.10.0","handlingStrategy":"validation","validationCode":"import re\n\ndef valid_migration_release(value: str) -> bool:\n    return re.fullmatch(r\"\\d+\\.\\d+\\.\\d+\", value) is not None","typeGuard":"import re\n\ndef is_three_segment_semver(value: str) -> bool:\n    return bool(re.fullmatch(r\"\\d+\\.\\d+\\.\\d+\", value))","tryCatchPattern":null,"preventionTips":["Strip 'v' prefixes and pre-release suffixes before passing --migration-release.","Copy the exact convention from existing entries in migration_table.json."],"tags":["cli","semver","validation","migration"],"backgroundTag":null,"analyzedSha":"976ec789d2886a86de109c044d089d68e96c9a35","analyzedAt":"2026-08-14T18:23:12.227Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}