Nodes/ComfyUI-CustomNodePacks/Batch Version Manager
ComfyUI Node

Batch Version Manager

Never save over a render again — auto-versioned output directories straight from a node

By Code2Collapse·Created 6 months ago·Updated a day ago· 52
Batch Version Manager
    • version_path
    • version_int
    • version_label
    • info_json
    root
    showshow
    shotsh010
    taskcomp
    reservefalse
    padding3
    max_retries5
    min_version1
    forward_slashtrue
    write_manifesttrue

    If you've ever overwritten a good render with a worse one - and then spent an hour not finding the undo - you know the pain this node removes. BatchVersionManagerMEC computes the next free v### directory under a <root>/<show>/<shot>/<task>/ structure and hands you a path you can feed to Save Image. Turn on reserve and it atomically claims the version with a lock file, so two queued prompts (or two machines) can't collide on the same folder.

    This is squarely aimed at the VFX/studio workflow, where the pack itself lives: shows, shots, tasks, versions. But it's just as useful for a solo user doing batch sweeps who's tired of manually renaming outputs. Same pack also ships a filesystem-scanning FolderIncrementer family; BatchVersionManager is the stricter, structure-aware sibling.

    How it works

    The node scans the task directory for existing v### folders, takes the max, and adds one (floored at min_version). With reserve=False it only computes the path - no disk writes at all. With reserve=True it creates the folder and writes a .lock file using exclusive creation, so if another process grabs the same version mid-race, it gets a FileExistsError and advances to the next number and retries, up to max_retries. No lock file, no reservation; that's the whole trick. When you reserve, it also writes a version_manifest.json sidecar (workflow hash, user, host, timestamp, show/shot/task) for a full audit trail - genuinely handy when you need to know exactly which settings produced which pass.

    The inputs that matter

    • root - absolute output root, e.g. D:/projects/renders.
    • show / shot / task - the three levels of the folder tree. Defaults are show / sh010 / comp.
    • reserve - the big one. Off = just tell me the next version. On = claim it.
    • padding (3) - v001 vs v0001.
    • max_retries (5) - how hard to fight for a version under contention.
    • min_version (1), forward_slash (true), write_manifest (true) - tweak as needed.

    Outputs are the four things you'll wire into Save Image: version_path (full path to the folder), version_int, version_label (v001), and info_json with the reservation metadata.

    Installing it

    Part of the ComfyUI-CustomNodePacks umbrella pack. ComfyUI Manager → search "CustomNodePacks", or:

    cd ComfyUI/custom_nodes
    git clone https://github.com/Code2Collapse/ComfyUI-CustomNodePacks.git
    

    Restart ComfyUI. Pure filesystem logic - no models, no extra pip packages. (As always with this pack, don't blanket pip install -r requirements.txt over ComfyUI's own torch/numpy; install only what you're missing.)

    Gotchas

    The root path is required - the node raises if it's empty, so wire it before your first run. Version-name characters in show/shot/task get sanitized for filesystem safety, which means your pretty names might come back slightly different from what you typed; that's deliberate. And if you see the "max_retries failed" error, it means another process is actively racing you for the same task directory - either raise max_retries or give the task triple a more unique name. Finally, remember that reserve=True creates the folder on the first run of the workflow; on a re-queue you'll get a fresh v###, which is exactly the behavior you want if you use it, and slightly surprising if you expected idempotence.

    CategoryC2C/IO

    Inputs (10)

    NameTypeDefaultDescription
    rootSTRINGAbsolute output root (e.g. D:/projects/renders).
    showSTRINGshowShow / project name (top-level folder under root)
    shotSTRINGsh010Shot identifier (folder under show)
    taskSTRINGcompTask name (folder under shot, e.g. comp, matte, render)
    reserveoptBOOLEANfalseAtomically reserve the version with a .lock file. When False, only computes the path — no disk writes.
    paddingoptINT31–6Zero-pad width for v### (3 → v001, 4 → v0001).
    max_retriesoptINT51–50On lock-race contention, advance version and retry this many times.
    min_versionoptINT11–999999Floor for the first version when no v### exists yet.
    forward_slashoptBOOLEANtrueWhen True (default), output paths use forward slashes for cross-platform compatibility. Set False to keep native (Windows backslash) separators.
    write_manifestoptBOOLEANtrueWhen `reserve=True`, also write `version_manifest.json` alongside the .lock containing workflow_hash + user + host + timestamp + show/shot/task triple. Provides full audit trail. Ignored when reserve=False.

    Outputs (4)

    NameTypeDescription
    version_pathSTRINGFull path to the next-version directory (forward-slash by default).
    version_intINTInteger version number that was allocated.
    version_labelSTRINGPadded version label such as v001.
    info_jsonSTRINGJSON metadata: show, shot, task, user, host, timestamp, reservation status.