Run a local n8n workflow against a small Node worker and ImageMagick. The worker records each input and output hash, binds approval to the exact output you reviewed, and exports only approved files. A missing or broken file stops at repair instead of forcing the whole batch through again.
In this guide
- When a recurring image batch is worth automating
- What you need before you start
- Where the pieces run
- Start the worker
- Check the worker before importing the flow
- Install and start n8n
- Import the two n8n workflows
- Set the run configuration
- Use your own images
- Run the first batch
- Check the outputs
- Approve only the version you checked
- Repair the failed image and retry one task
- Export the approved batch
- Handle duplicate triggers and real errors
- Stop and reset the lab
- Does this workflow need an AI model?
- Can this run on a VPS?
- How are small images handled?
- What this version does not cover
- The files and the test record
When a recurring image batch is worth automating
Use this workflow when product photos arrive in repeating batches and the same checks have to happen every time: fit inside a maximum size, preserve the aspect ratio, do not enlarge a small image, and keep a record of what was processed and approved. It is a poor fit for a one-off image that a desktop editor can handle in a minute.
The processing is deterministic JPEG resize and compression. The workflow does not remove backgrounds, generate new pixels, retouch a product, or judge whether an image looks good. A person opens the output and approves it before export.
What you need before you start
The package includes the worker, both n8n workflows, three practice images, reference outputs, and run reports. You supply the local runtimes.
- Windows 10 Pro x64 on the tested path. The run used 8 GB RAM.
- ImageMagick 7.1.2-34 Q16-HDRI. The worker calls the magick executable directly.
- Node.js 22.13.0 for the worker.
- Node.js 24.22.1 and n8n 2.44.5 for the workflow editor. n8n 2.44 requires Node 24 or newer.
- A local folder where you can read and write the package files. The worker binds to 127.0.0.1 and is not a public service.
- Images you own or have permission to process. The supplied practice images are synthetic graphics, not customer photos.
Where the pieces run
n8n is the orchestrator. It starts the batch, calls the worker, reads the result, and chooses the repair, approval, error, or export branch.
The Node worker is a small HTTP service. It reads input/manifest.json, calls ImageMagick, checks the output, and stores task state. ImageMagick performs the resize and JPEG compression. The filesystem holds the inputs, outputs, quarantine copies, reports, and approvals.
n8n
Manual trigger, health check, POST /run, branch on the report, and POST /export only after every task is approved.
Worker
One local process on 127.0.0.1:8765. It owns the queue lock, task history, output checks, and approval hashes.
ImageMagick
Runs the resize and compression command. The worker passes the file path and checks the result afterward.
Files
input/, output/, quarantine/, state/, reports/, and export/. No database server and no cloud bucket are used.
Start the worker
Unzip the package, open PowerShell in the package folder, and point the worker at the ImageMagick executable. Start the worker in its own terminal.
$env:IMAGEMAGICK_PATH = "C:\Program Files\ImageMagick-7.1.2-Q16-HDRI\magick.exe" node worker\server.mjs
Check the worker before importing the flow
In a second terminal, ask the worker for its health response. It should report status ok and the ImageMagick version. If the version is missing, fix the executable path before continuing.
The worker prints the lab root and the configuration path when it starts. Keep those two paths visible; they tell you which files the run will use.
node worker\cli.mjs health
Install and start n8n
Use Node.js 24 for n8n and keep the n8n runtime outside the package. The tested machine completed the install with pnpm after the local npm install failed with a machine-specific error, so this is not a clean-machine installation pass. The pinned version and the start command are the parts to reproduce.
Open http://127.0.0.1:5678 for the editor. The first start creates the local SQLite database and asks for a local owner account. No cloud login is required.
node --version mkdir n8n-runtime cd n8n-runtime npm init -y npm install [email protected] npx n8n start
Import the two n8n workflows
The package contains two exported workflows in n8n/exported/. In the n8n editor, use Import from File for each one. The exports contain no credentials.
The run workflow processes the manifest. The retry workflow sends one repaired task back to the worker. Both use a Manual Trigger, so nothing runs on a schedule until you add one deliberately.
- w1-run-batch.json: health check, batch run, error and failure branches, approval check, and export.
- w1-retry-one.json: one failed task after you replace its input.
- Change worker_url in both Run config and Retry config if you move the worker to another local port.
Manual Trigger
-> Run config
-> Worker health
-> Run image queue
-> Build run report
-> Busy?
true -> Run busy
false -> Error?
true -> Stop with error
false -> Any failures?
true -> Repair needed
false -> All approved?
true -> Export approved -> Done
false -> Awaiting approvalSet the run configuration
Open the Run config node and check the run ID and worker URL. Use a new run_id for a new batch. State is stored in state/<run_id>.json and outputs go under output/<run_id>/, so a later run does not overwrite an earlier one.
The processing settings are in config/default.json. The worker reads this file once at startup. If you change the size or quality, stop the worker and start it again before the next run; editing the file while the worker is running leaves the old values in memory.
| Setting | Tested value | Effect |
|---|---|---|
| maxWidth / maxHeight | 1600 / 1600 | Fits the image inside a 1600 x 1600 box. |
| quality | 82 | JPEG compression quality used in the tested run. |
| allowUpscale | false | A smaller image is not enlarged. |
| concurrency | 1 | One run, retry, approval, or export at a time across the worker. |
run_id = run-2026-10-21-n8n worker_url = http://127.0.0.1:8765
Use your own images
The practice manifest is a working example, not a fixed list. Put your JPEGs in input/, back up the practice input/manifest.json, and save your own list as input/manifest.json. The worker reads that exact filename; a different name is ignored.
Give each file a unique task_id. Do not reuse an ID for a different image or a later rework. Write each input path relative to the package root. Set a new run_id in the n8n Run config node; the run_label in the manifest is only a human label.
- Back up the practice input/manifest.json.
- Save your own list as input/manifest.json.
- Use one unique task_id per image.
- Write paths such as input/sku-1001-front.jpg.
- Set a new run_id in the Run config node.
{
"run_label": "store-batch-2026-11-02",
"items": [
{ "task_id": "sku-1001-front", "input": "input/sku-1001-front.jpg" },
{ "task_id": "sku-1001-side", "input": "input/sku-1001-side.jpg" },
{ "task_id": "sku-1002-front", "input": "input/sku-1002-front.jpg" }
]
}Run the first batch
The practice manifest has three tasks. image-03.jpg is deliberately corrupted. Execute w1 image queue - run batch and expect the failure branch, not an export.
The worker checks file existence, decode, JPEG format, dimensions, no-upscale, original hash, and output-to-task naming. It records the result and isolates the bad input in quarantine/<run_id>/.
The n8n flow should end at Repair needed. The two valid images were not held back by the third failure, and the bad file was not counted as a success. The local first execution took about 1.67 seconds; that is a small local observation, not a throughput promise.
| Task | Input | First result |
|---|---|---|
| image-01 | 2400 x 1800 JPEG | success, 1600 x 1200, 46,203 bytes |
| image-02 | 800 x 800 JPEG | success, 800 x 800, 21,550 bytes |
| image-03 | corrupted JPEG | failed at decode, input quarantined, no valid output |
Check the outputs
Open output/run-2026-10-21-n8n/image-01-v1.jpg and image-02-v1.jpg. The composition should match the input at the new size. The worker confirms validity and dimensions; it does not judge crop, subject, or visual quality.
- The output exists and decodes as an image.
- The format is JPEG.
- The dimensions fit inside 1600 x 1600 with the aspect ratio preserved.
- A smaller input was not enlarged.
- The original input hash did not change.
- The output path matches the task and attempt.
Approve only the version you checked
Approval is tied to the output hash. After you inspect an output, approve it with the command-line client. A changed file or a wrong hash is rejected, and export will not accept an approved task whose output no longer matches.
Approving one output does not finish the batch. If some tasks are still successful but unapproved, the n8n flow stays at Awaiting approval. It does not mark the batch done or export a partial set.
node worker\cli.mjs approve run-2026-10-21-n8n image-01 node worker\cli.mjs approve run-2026-10-21-n8n image-02
Repair the failed image and retry one task
The broken image-03.jpg is preserved in quarantine/run-2026-10-21-n8n/image-03-v1-input.jpg. Replace the input with the supplied valid image, then run the retry workflow or use the CLI.
Ordinary retry accepts only a failed task. Retrying an approved or successful task returns HTTP 409 and does not create a new attempt or output. To rework an approved image, start a new run with a new run_id.
- image-03 attempt 2, success, 1200 x 900, 32,143 bytes.
- image-01 and image-02 remain attempt 1 with unchanged outputs.
- The old broken input remains in quarantine.
- The failed first attempt remains in image-03.history.
Copy-Item input\image-03-valid.jpg input\image-03.jpg -Force node worker\cli.mjs retry run-2026-10-21-n8n image-03
Export the approved batch
Run w1 image queue - run batch again after all three tasks are approved. The worker skips the approved tasks, All approved? is true, and the flow takes Export approved to Done.
Only approved outputs are copied to export/run-2026-10-21-n8n/. The manifest records the input path, input hash, output path, output hash, dimensions, and approval time. The default export requires every task in the run to be approved.
A partial export exists only as an explicit command-line choice. Its manifest sets partial true and lists the tasks that were not approved. The n8n workflow never calls this mode; it waits at Awaiting approval instead.
node worker\cli.mjs export run-2026-10-21-n8n node worker\cli.mjs export run-2026-10-21-n8n --partial
Handle duplicate triggers and real errors
A second trigger during an active run receives HTTP 409 with the code worker_busy, and n8n takes Run busy. The duplicate request is not processed and does not create extra attempts. The worker-wide lock in state/worker.lock is what makes concurrency 1 real.
The lock does not expire by age. A long batch can run for more than ten minutes, so the worker never removes a lock just because the file is old. If a crashed worker leaves the lock behind, stop every worker, confirm no operation is active, delete state/worker.lock manually, and start one worker again.
A broken manifest, a worker 500, or a connection failure is not a busy signal. The Error? branch sends those to Stop with error, keeps the original message, and marks the n8n execution as an error. Only the explicit worker_busy code reaches Run busy.
Stop and reset the lab
Both workflows use a Manual Trigger. Stop the n8n process and the worker process when you are finished; there is no background schedule to pause.
Before removing quarantine, restore the deliberately broken practice input if you still need it. Then archive or remove state/, output/, quarantine/, export/, and reports/, and start the worker again with the new configuration loaded. Use a new run_id for the next batch.
Copy-Item quarantine\run-2026-10-21-n8n\image-03-v1-input.jpg input\image-03.jpg -Force
Does this workflow need an AI model?
No. The processing step is ImageMagick resizing and JPEG compression. n8n orchestrates the steps and does not send the image to a model. The version has no token charge and no model-generated pixels.
Can this run on a VPS?
The components are designed for a machine you control, but this build was tested only on Windows 10. A Linux VPS would need its own install, permissions, service, and storage checks. This page does not claim that branch is verified.
How are small images handled?
The resize geometry is 1600x1600 with a trailing >, which only shrinks. The tested 800 x 800 input stayed 800 x 800, and a separate check fails the task if the output becomes larger than the input.
What this version does not cover
The tested path is JPEG on Windows. Keep these limits visible when you adapt the workflow.
- PNG, transparency, EXIF orientation, and color-profile conversion are not claimed as tested.
- A VPS, Docker, service management, and Linux permissions are not tested.
- The checker does not score visual quality, similarity, or brand accuracy.
- The worker has no authentication and binds to 127.0.0.1. Do not expose port 8765 to the internet.
- No throughput, cost-saving ratio, or provider ranking is claimed from three small images.
The files and the test record
The package contains the worker, authored and exported n8n workflows, practice inputs, reference outputs, and run reports. VERSIONS.md records the tested versions; TROUBLESHOOTING.md covers common setup and recovery failures.
The recorded practice result is intentionally specific: image-01 changed from 2400 x 1800 to 1600 x 1200 at 46,203 bytes; image-02 stayed 800 x 800 at 21,550 bytes; image-03 failed at decode, then became 1200 x 900 at 32,143 bytes after repair. The first n8n run produced two successes and one failure. The retry touched only image-03. The export contained three approved images and a hash manifest.
References
Documentation checked 2026-10-22.
Continue the task
Keep the image batch reviewable by separating processing, approval, and export.
