{"record":{"id":"87055622ed17a923","repo":"langflow-ai/langflow","slug":"error-source-entries-field-must-be-a-list","errorCode":null,"errorMessage":"error: {source} entries field must be a list","messagePattern":"error: (.+?) entries field must be a list","errorType":"console","errorClass":"SystemExit","httpStatus":null,"severity":"error","filePath":"scripts/migrate/check_migration_append_only.py","lineNumber":100,"sourceCode":"\ndef _parse(raw: str, *, source: str) -> tuple[list[dict], list[dict]]:\n    \"\"\"Return ``(entries, ambiguous_bare_names)`` from a migration-table JSON.\n\n    Both lists default to empty when the field is absent so this script can\n    compare across baselines that pre-date a given field.\n    \"\"\"\n    try:\n        data = json.loads(raw)\n    except json.JSONDecodeError as exc:\n        print(f\"error: invalid JSON in {source}: {exc}\", file=sys.stderr)\n        raise SystemExit(2) from exc\n    if not isinstance(data, dict):\n        print(f\"error: {source} top-level value must be an object\", file=sys.stderr)\n        raise SystemExit(2)\n    entries = data.get(\"entries\", [])\n    if not isinstance(entries, list):\n        print(f\"error: {source} entries field must be a list\", file=sys.stderr)\n        raise SystemExit(2)\n    ambig = data.get(\"ambiguous_bare_names\", [])\n    if not isinstance(ambig, list):\n        print(f\"error: {source} ambiguous_bare_names field must be a list\", file=sys.stderr)\n        raise SystemExit(2)\n    return entries, ambig\n\n\ndef _compare(baseline: list[dict], current: list[dict]) -> list[str]:\n    \"\"\"Return human-readable violations; empty list means clean.\"\"\"\n    violations: list[str] = []\n    current_by_key: dict[tuple[str, str], dict] = {}\n    for entry in current:\n        try:\n            key = _entry_key(entry)\n        except ValueError as exc:\n            violations.append(str(exc))\n            continue\n        if key in current_by_key:","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/langflow-ai/langflow/blob/976ec789d2886a86de109c044d089d68e96c9a35/scripts/migrate/check_migration_append_only.py#L82-L118","documentation":"This error comes from scripts/migrate/check_migration_append_only.py, a CI guard that compares the working-tree migration_table.json against a baseline to enforce that the extension migration table is append-only. After parsing the JSON and confirming the top-level value is an object, it reads data['entries'] and requires it to be a Python list, because each entry maps a legacy component form to its new ext:<bundle> target. If 'entries' is present but not a list (a dict, string, number, or null), the script prints 'error: {source} entries field must be a list' to stderr and exits with code 2 (usage / I/O error).","triggerScenarios":"Running `python scripts/migrate/check_migration_append_only.py` (or with --baseline/--current) where src/lfx/src/lfx/extension/migration/migration_table.json, or the baseline fetched via `git show <base>:src/lfx/src/lfx/extension/migration/migration_table.json`, contains an 'entries' key whose value is not a JSON array — e.g. \"entries\": {...} or \"entries\": \"none\". A missing 'entries' key does NOT trigger it (data.get('entries', []) defaults to []).","commonSituations":"Hand-editing migration_table.json and accidentally nesting entries under a keyed object (e.g. grouping by provider) instead of an array; a merge conflict resolution that left a stray string; feeding a --baseline file that is actually a different schema (e.g. an export or report) rather than a migration table.","solutions":["Open the file named in the error message and change the 'entries' value to a JSON array of entry objects: \"entries\": [ { ... }, ... ].","If you intentionally restructured the table, revert to the documented schema (top-level object with 'entries' list and 'ambiguous_bare_names' list) — the runtime lfx extension migration reader expects exactly that shape.","If the error names the baseline side, check `git show <base>:src/lfx/src/lfx/extension/migration/migration_table.json | python -m json.tool` to see the malformed value at that ref, or point --baseline at a known-good copy.","Validate locally before pushing: `python -c \"import json;d=json.load(open('src/lfx/src/lfx/extension/migration/migration_table.json'));assert isinstance(d['entries'],list)\"`."],"exampleFix":"// before (migration_table.json)\n{\n  \"entries\": {\n    \"ChatInput\": { \"target\": \"ext:helpers:ChatInput\" }\n  },\n  \"ambiguous_bare_names\": []\n}\n\n// after\n{\n  \"entries\": [\n    { \"bare_class_name\": \"ChatInput\", \"target\": \"ext:helpers:ChatInput@official\" }\n  ],\n  \"ambiguous_bare_names\": []\n}","handlingStrategy":"validation","validationCode":"import json\n\nMANIFEST = \"src/lfx/src/lfx/extension/migration/migration_table.json\"\n\ndef manifest_is_valid(path: str = MANIFEST) -> bool:\n    data = json.loads(open(path, encoding=\"utf-8\").read())\n    return (\n        isinstance(data, dict)\n        and isinstance(data.get(\"entries\", []), list)\n        and isinstance(data.get(\"ambiguous_bare_names\", []), list)\n    )\n\nassert manifest_is_valid(), \"run before scripts/migrate/check_migration_append_only.py\"","typeGuard":"def is_migration_manifest(data: object) -> bool:\n    \"\"\"Narrow parsed JSON to the migration-table shape.\"\"\"\n    if not isinstance(data, dict):\n        return False\n    entries = data.get(\"entries\", [])\n    ambig = data.get(\"ambiguous_bare_names\", [])\n    return (\n        isinstance(entries, list)\n        and all(isinstance(e, dict) for e in entries)\n        and isinstance(ambig, list)\n        and all(isinstance(e, dict) for e in ambig)\n    )","tryCatchPattern":null,"preventionTips":["Never hand-restructure migration_table.json into keyed objects; the schema is a fixed top-level object with two arrays.","Add a pre-commit hook that json.loads the table and asserts both fields are lists.","Treat exit code 2 from check_migration_append_only.py as schema/usage breakage (fix the file), exit code 1 as real append-only violations (fix the diff)."],"tags":["json","migration","validation","ci"],"backgroundTag":null,"analyzedSha":"976ec789d2886a86de109c044d089d68e96c9a35","analyzedAt":"2026-08-14T18:23:12.227Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}