Local Run Receipts: Commit Image Run
The ComfyUI Output Node That Refuses to Overwrite a Good Run
- images
- status
- receipt_path
Stop losing runs to an accidental retry
Drop Local Run Receipts: Commit Image Run where you'd normally put a Save Image node, and your results stop silently getting clobbered. Instead of stamping ComfyUI_00001_.png into output/ and happily writing over whatever was there, it saves your images into a per-run folder named after a stable key, writes a small receipt.json next to them, and - the important part - stops the workflow with a loud conflict if you ever try to save different pixels under the same key again.
It's built for the workflows where overwriting is worse than failing: batch runs, parameter sweeps, overnight generations you plan to compare later. Run a sweep, discover run #7 was the good one, and re-queue the graph - only to find run-007.png is now a different image. This node makes that impossible: same key plus identical bytes returns ALREADY_IDENTICAL and touches nothing; same key plus different bytes raises a conflict and refuses to write. Either way, the good run survives.
How it works
You feed it three things: your final images batch plus the run_key and canonical_record strings from Local Run Receipts: Build Run Key. The commit node re-derives the expected SHA-256 from the record and verifies it matches the key you passed - if they disagree it errors, so you can't wire a key to the wrong record.
Everything lands under ComfyUI's normal output directory:
output/
local-run-receipts/
lrr1_<sha256>/
run-001.png
run-002.png
receipt.json
Images are written first, receipt.json last - the receipt is the commit marker, which is why a directory with images but no receipt counts as incomplete and is never touched. Files are written atomically (temp file + rename), so a crash can't leave a half-written PNG that later passes for a real run. On a repeat run the node hashes the stored images and compares the stored receipt byte-for-byte; only a full match returns ALREADY_IDENTICAL.
The engine detail that makes any of this work: the node marks itself changed every run (its IS_CHANGED returns NaN, the same trick random-seed nodes use), so ComfyUI never replays a cached output-node result and actually re-inspects the receipt each time. The cost is that it defeats the cache behind it - which is fine, because the whole point is that it must run.
Inputs and outputs that matter
images- your final IMAGE batch. Anything HxWx3 or HxWx4 works.run_key/canonical_record- straight from Build Run Key. Both required; they're checked against each other.output_subfolder(defaultlocal-run-receipts) - where the key folders live. Only safe relative paths are accepted; it cannot write outside ComfyUI's output directory.filename_prefix(defaultrun) - the name stem, producingrun-001.png,run-002.png, and so on.
Outputs: status (CREATED or ALREADY_IDENTICAL) and receipt_path (the relative path to receipt.json, e.g. local-run-receipts/lrr1_<sha256>/receipt.json). Both show up in the UI, and you can wire them into a note node if you like.
One honest trade-off vs. stock SaveImage: these PNGs carry no embedded ComfyUI workflow metadata. The run's record lives in receipt.json - the declared key inputs, a SHA-256 of the prompt (runtime cache markers stripped so cosmetic changes don't break the key), and each image's hash, size, and dimensions. If you rely on dragging a PNG back onto the canvas to rebuild a workflow, this swaps that convenience for a strict, verifiable manifest.
Install
The pack is brand new and the Registry listing is pending, so until it's live, clone and restart:
cd ComfyUI/custom_nodes
git clone https://github.com/nawnie/ComfyUI-Local-Run-Receipts
Then restart ComfyUI. Once the Registry listing is live you can search "Local Run Receipts" in ComfyUI Manager instead. No models, no network code, no heavy dependencies - just Pillow and NumPy, which ComfyUI already ships (needs ComfyUI 0.28.0+).
Troubleshooting
- Conflict errors are the feature, not a bug. The workflow stops and tells you the stored receipt or image bytes differ from this run. If you genuinely meant to replace the old run, delete (or move) its folder under
output/local-run-receipts/- or change a declared value in Build Run Key to get a fresh key. - "Run key is incomplete and will not be overwritten" - a directory has images but no
receipt.json(a crash, or a manual cleanup). The node refuses to touch it by design; remove the partial folder yourself. - ComfyUI replays the same result without checking - the commit node isn't actually executing. It must be the final output node in the graph, wired from your real image output, not bypassed or muted.
For most people this node is a belt-and-suspenders habit: put it on the run you're going to compare or publish, not on every iteration of a sketch. When it saves you one overwritten masterpiece, it's paid for itself.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| images | IMAGE | The images to commit under the run key. | |
| run_key | STRING | — | |
| canonical_record | STRING | — | |
| output_subfolder | STRING | local-run-receipts | — |
| filename_prefix | STRING | run | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| status | STRING | — |
| receipt_path | STRING | — |