PixlStash Upscale Model Loader
The upscaler grid that tells you which file you meant
- upscale_model
Upscaling arguments are usually two people doing different jobs, so know which job this node does first. This loader is for more pixels: the image already has the detail, you need it bigger - ESRGAN-family models like 4x-UltraSharp or Remacri, milliseconds on almost no VRAM, inventing nothing. Want more detail - pores, lashes, repaired compression? That's SeedVR2 or SUPIR, and not any file this node loads.
So what does the PixlStash Upscale Model Loader do that Load Upscale Model doesn't? Replaces the dropdown with a thumbnail grid from a PixlStash model shelf. Sounds small until you count the files: 4x-UltraSharp.pth, 4x_foolhardy_Remacri.pth, RealESRGAN_x4plus.pth, plus three variants a tutorial made you download in 2024. They're all 4x_ something. The shelf shows the entry with its picture, so you stop guessing and stop re-testing.
Be clear-eyed about the trade. It needs a running PixlStash - a self-hosted image library by the same solo author - and an owner API token. Four upscale models and no PixlStash? Use the built-in. This one's for people already filing their generations there.
How it actually loads
The one widget is upscale_model_sha256, a digest the Browse button writes, per the author's own tooltip. The file is addressed by content, so re-foldering on the server doesn't break your workflow.
At queue time the node fetches the shelf's record for that digest. If PixlStash and ComfyUI share a filesystem and the copy is there at the recorded byte size, the model loads in place. Otherwise it downloads once to models/upscale_models/pixlstash/<sha256>.pth (or .safetensors, matching the source), hashing as it streams and renaming into place only after the digest checks out. Unlike the pack's other loaders this one takes .pth too - which matters, because nearly every upscaler ever trained ships as one.
The interesting bit is what happens after the path resolves: it doesn't reimplement loading. ComfyUI has no public load-an-upscaler-by-path call, and what the loader hands downstream changes between releases (recent ImageUpscaleWithModel reads a patcher the loader attaches). So for one load it swaps folder_paths.get_full_path so the built-in answers the absolute path for itself, calls ComfyUI's own UpscaleModelLoader, then puts it back, behind a lock. A cheeky shim, and the right call: what reaches Upscale Image stays whatever your ComfyUI expects, so this node doesn't rot on the next update.
What you wire
upscale_model_sha256 in; empty means a clear RuntimeError telling you to click Browse, not a crash downstream. upscale_model (UPSCALE_MODEL) out, straight into Upscale Image (using Model), which owns the scale: the model is a 4x network, so 2x means scale_by 0.5 there. This loader has no opinion about size, method or overlap - it's a file picker with a socket, and it drops into an existing graph with no rewiring. It also stamps a pixlstash_lock entry naming the upscaler onto the run, so PixlStash later knows which model made a picture.
Installing it
ComfyUI Manager → search ComfyUI-PixlStash → Install → restart. Or:
cd ComfyUI/custom_nodes
git clone https://github.com/Pikselkroken/ComfyUI-PixlStash.git
# restart, then Settings > PixlStash
Deps are requests and Pillow; the pack asks for ComfyUI 0.20.0 or newer. (The optional gguf package the README mentions is for GGUF checkpoints - irrelevant here.)
Then Settings › PixlStash: URL, API token, and Verify SSL if you're on a self-signed cert. The token must be an owner token; share tokens get a 403 from the shelf even though they work for pictures. You also need PixlStash 1.12 or newer, which catalogs .pth upscalers as their own kind - the node checks the version first and names both if yours is older.
Where it bites
It refuses your file with "which this node does not load". That's the extension check - anything that isn't .pth or .safetensors is turned away before a byte is downloaded. It's a feature, and it will still catch you.
An old, weird .pth won't load. The built-in reads .pth with torch's weights_only unpickler, which refuses anything that isn't tensors and plain containers. Ordinary ESRGAN-style state dicts are fine.
Hash-named files appear in your stock dropdown. Cached downloads sit in models/upscale_models/pixlstash/ named by digest and nothing evicts them: 64 hex characters in the built-in loader, forever. Delete them by hand when the disk gets tight; the next run fetches again.
"No usable copy of this file is on this machine." The server couldn't hand over the bytes, or ComfyUI and PixlStash don't share the storage you assumed. The line "is not the file the shelf describes (N bytes here, M on the shelf)" is that diagnosis spelled out - common on a NAS, where the shelf recorded the server's own paths and the mount on the ComfyUI box differs.
Shared ComfyUI. The pack refuses to run in multi-user setups rather than risk using someone else's token - ComfyUI doesn't tell a node who queued the prompt. One single-user ComfyUI per PixlStash user.
Inputs (1)
| Name | Type | Default | Description |
|---|---|---|---|
| upscale_model_sha256 | STRING | Written by the Browse button — the SHA-256 of the upscaler on the shelf. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| upscale_model | UPSCALE_MODEL | The upscale model, for an Upscale Image (using Model). |