{"record":{"id":"90b3de7077d51ea0","repo":"langflow-ai/langflow","slug":"git-is-not-available-cannot-check-append-only-inv","errorCode":null,"errorMessage":"git is not available; cannot check append-only invariant.","messagePattern":"git is not available; cannot check append-only invariant\\.","errorType":"console","errorClass":"SystemExit","httpStatus":null,"severity":"error","filePath":"scripts/migrate/check_migration_append_only.py","lineNumber":75,"sourceCode":"\ndef _git_show(ref: str, relpath: str) -> str | None:\n    \"\"\"Return the contents of ``relpath`` at ``ref``, or ``None`` if absent.\n\n    Absence is the common-case on initial introduction of the table file:\n    the baseline simply doesn't have the file yet, in which case there is\n    nothing to compare against and the check trivially passes.\n    \"\"\"\n    try:\n        completed = subprocess.run(  # noqa: S603 - git invoked with a fixed argv list\n            [\"git\", \"show\", f\"{ref}:{relpath}\"],  # noqa: S607 - git resolves via PATH like every CI runner\n            check=False,\n            capture_output=True,\n            text=True,\n            cwd=REPO_ROOT,\n        )\n    except FileNotFoundError:  # git not on PATH\n        msg = \"git is not available; cannot check append-only invariant.\"\n        raise SystemExit(msg) from None\n    if completed.returncode != 0:\n        # Most likely: file not present at base ref.  We treat that as\n        # \"no baseline\" and return None.\n        return None\n    return completed.stdout\n\n\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","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/langflow-ai/langflow/blob/976ec789d2886a86de109c044d089d68e96c9a35/scripts/migrate/check_migration_append_only.py#L57-L93","documentation":"Raised by scripts/migrate/check_migration_append_only.py when it cannot invoke `git` (subprocess raises FileNotFoundError) while trying to `git show` the migration-table JSON at a baseline ref. The script compares current migration entries against the baseline to enforce append-only history; without git there is no baseline, so it exits rather than silently passing.","triggerScenarios":"Running the migration check in an environment where git is not installed or not on PATH — minimal CI containers (python:slim without git), some Docker images, or restricted sandboxes — while the checkout includes a .git directory.","commonSituations":"CI images optimized to Python-only tooling; local venvs launched from GUI launchers that strip PATH; pipelines that archive the repo without .git (that yields the 'no baseline' pass, distinct from this).","solutions":["Install git in the environment (apt-get install -y git / apk add git) and re-run the script","Verify with `which git` in the exact shell/container the script runs in","If git is intentionally absent and no baseline is needed, export the repo without a .git directory — the script then treats it as 'no baseline' and passes trivially","In CI, use a base image that bundles git (e.g. ci- prefixed images)"],"exampleFix":"# before — Dockerfile with no git\nFROM python:3.12-slim\nRUN pip install -r requirements.txt\n\n# after\nFROM python:3.12-slim\nRUN apt-get update && apt-get install -y --no-install-recommends git && rm -rf /var/lib/apt/lists/*\nRUN pip install -r requirements.txt","handlingStrategy":"validation","validationCode":"import shutil\nif shutil.which(\"git\") is None:\n    print(\"skipping append-only check: git not installed\")\n    sys.exit(0)  # or fail loudly, per your CI policy","typeGuard":null,"tryCatchPattern":"# script already exits via SystemExit; wrap invocation instead:\nimport subprocess, sys\nr = subprocess.run([sys.executable, \"scripts/migrate/check_migration_append_only.py\"])\nif r.returncode != 0 and shutil.which(\"git\") is None:\n    print(\"pre-flight failed: install git in this image\")","preventionTips":["Use CI base images that include git when migration checks run","Add `which git` to pipeline pre-flight checks","Document that the script needs a real .git checkout plus git on PATH"],"tags":["python","ci","git","migrations","tooling","environment"],"backgroundTag":null,"analyzedSha":"976ec789d2886a86de109c044d089d68e96c9a35","analyzedAt":"2026-08-14T18:23:12.227Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}