Skip to content

bug: infrahub-task-worker crashloops with BranchData ValidationError when a branch is in MERGING status (SDK enum missing MERGING) #9293

Description

@PhillSimonds

Component

Python SDK, Git Integration

Infrahub version

1.9.4 (also reproducible against 1.9.3 and 1.9.5 by code inspection)

Current Behavior

After upgrading to 1.9.4, infrahub-task-worker enters CrashLoopBackOff with the following exception on every scheduled run of the sync_remote_repositories flow:

pydantic_core._pydantic_core.ValidationError: 1 validation error for BranchData
status
  Input should be 'OPEN', 'NEED_REBASE', 'NEED_UPGRADE_REBASE', 'DELETING' or 'MERGED'
  [type=enum, input_value='MERGING', input_type=str]

The server-side BranchStatus enum (backend/infrahub/core/branch/enums.py) includes MERGING, added in PR #9116 (commit c6bf8720b, first released in 1.9.3):

class BranchStatus(InfrahubStringEnum):
    OPEN = "OPEN"
    NEED_REBASE = "NEED_REBASE"
    NEED_UPGRADE_REBASE = "NEED_UPGRADE_REBASE"
    DELETING = "DELETING"
    MERGING = "MERGING"
    MERGED = "MERGED"

The Python SDK's BranchStatus enum (infrahub_sdk/branch.py lines 17-22) does not include MERGING:

class BranchStatus(str, Enum):
    OPEN = "OPEN"
    NEED_REBASE = "NEED_REBASE"
    NEED_UPGRADE_REBASE = "NEED_UPGRADE_REBASE"
    DELETING = "DELETING"
    MERGED = "MERGED"

The python_sdk submodule pin in tags infrahub-v1.9.3, infrahub-v1.9.4, and infrahub-v1.9.5 is commit dec31010, which is missing MERGING. SDK main (v1.20.0) is also missing it.

The task worker hits this on backend/infrahub/git/tasks.py:222:

branches = await client.branch.all()

BranchManager.all() constructs BranchData(**branch) per branch, so any branch returned with status="MERGING" raises ValidationError and aborts the entire flow.

How a branch ends up in MERGING: _do_merge_branch in backend/infrahub/core/branch/tasks.py:391 sets branch.status = BranchStatus.MERGING before the merge, then transitions to MERGED (success, line 468) or back to OPEN (rollback, line 354). If the worker dies between those points (OOM, container restart, or any other abnormal termination that bypasses the BaseException rollback path), the branch is stranded in MERGING and every subsequent SDK call that materializes BranchData crashes.

Expected Behavior

  • The SDK's BranchStatus enum should be a superset of every value the server can return. Adding MERGING to the SDK should be part of the same release that introduced it server-side.
  • _do_merge_branch should guarantee that the branch never permanently ends in MERGING even if the worker is killed abnormally — either via a finally block that resets the branch to OPEN if neither the success nor the rollback path completed, or via a startup-time reconciler that releases MERGING branches whose merge task is no longer running.
  • client.branch.all() (and the task-worker flow that calls it) should be resilient to a single malformed branch entry rather than failing the whole batch.

Steps to Reproduce

  1. Deploy Infrahub 1.9.3, 1.9.4, or 1.9.5.
  2. Create a branch with schema changes and some data.
  3. Initiate a merge of that branch and kill the task worker mid-merge — between the MERGING transition (backend/infrahub/core/branch/tasks.py:391) and either MERGED (line 468) or the rollback (line 354).
  4. Restart the task worker. It will crashloop on the next sync_remote_repositories run because client.branch.all() cannot deserialize the stranded MERGING branch.

Alternative deterministic reproduction (no race required):

  1. Manually set any branch's status to "MERGING" in the graph (e.g. MATCH (b:Branch {name:"<name>"}) SET b.status="MERGING").
  2. Run the task worker — it will crashloop on the first client.branch.all() call.

Additional Information

  • Server enum addition: commit c6bf8720b ("greater rollback coverage of merge logic", PR greater rollback coverage of merge logic #9116), first tag infrahub-v1.9.3.
  • SDK BranchStatus: infrahub_sdk/branch.py lines 17-22 — last touched by PR feature: Run the demo environment on Windows without a VM #794 (829800d) which added MERGED but not MERGING.
  • SDK pin in affected server tags: submodule python_sdk at dec31010.
  • Suggested fix(es):
    1. Add MERGING = "MERGING" to infrahub_sdk.branch.BranchStatus, release a patch SDK, bump the python_sdk submodule pin in an Infrahub patch release.
    2. Wrap the merge body in try/except/finally so the branch is guaranteed to leave MERGING (back to OPEN if the success path did not complete) — or add a startup reconciler that detects stranded MERGING branches and resets them.
    3. Defensive: have BranchManager.all() skip/log malformed entries rather than failing the entire collection.

Metadata

Metadata

Assignees

No one assigned

    Labels

    type/bugSomething isn't working as expected

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions