Batch Version Manager
Never save over a render again — auto-versioned output directories straight from a node
- version_path
- version_int
- version_label
- info_json
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) -
v001vsv0001. - 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.
Inputs (10)
| Name | Type | Default | Description |
|---|---|---|---|
| root | STRING | Absolute output root (e.g. D:/projects/renders). | |
| show | STRING | show | Show / project name (top-level folder under root) |
| shot | STRING | sh010 | Shot identifier (folder under show) |
| task | STRING | comp | Task name (folder under shot, e.g. comp, matte, render) |
| reserveopt | BOOLEAN | false | Atomically reserve the version with a .lock file. When False, only computes the path — no disk writes. |
| paddingopt | INT | 31–6 | Zero-pad width for v### (3 → v001, 4 → v0001). |
| max_retriesopt | INT | 51–50 | On lock-race contention, advance version and retry this many times. |
| min_versionopt | INT | 11–999999 | Floor for the first version when no v### exists yet. |
| forward_slashopt | BOOLEAN | true | When True (default), output paths use forward slashes for cross-platform compatibility. Set False to keep native (Windows backslash) separators. |
| write_manifestopt | BOOLEAN | true | When `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)
| Name | Type | Description |
|---|---|---|
| version_path | STRING | Full path to the next-version directory (forward-slash by default). |
| version_int | INT | Integer version number that was allocated. |
| version_label | STRING | Padded version label such as v001. |
| info_json | STRING | JSON metadata: show, shot, task, user, host, timestamp, reservation status. |