ComfyUI debug & preview
Inspect values mid-graph without changing them. Read / log / visualize / time / report. Nothing in this skill mutates the data flow — these nodes either pass through unchanged (Preview Bridge, TimerNodeKJ) or are pure sinks (ShowText, CConsoleAny).
The split:
| Pack | Niche |
|---|---|
comfyui-custom-scripts (pysssss) |
ShowText — display text in node widget UI |
comfyui_essentials |
DisplayAny, ConsoleDebug, DebugTensorShape, BatchCount |
comfyui-kjnodes |
PreviewImageOrMask, FastPreview, VRAM_Debug, TimerNodeKJ, Sleep, Get(Image|Mask|Latent)SizeAndCount |
ComfyUI-Crystools |
CConsoleAny, CConsoleAnyToJson, CUtilsStatSystem (CPU/GPU/RAM monitor), CImageLoadWithMetadata, CMetadataExtractor, CMetadataCompare |
bjornulf_custom_nodes |
ShowFloat, ShowInt, ShowStringText, ShowJson, ImageDetails, VideoDetails |
comfyui-dream-project |
DreamStringToLog, DreamIntToLog, DreamFloatToLog, DreamJoinLog, DreamLogFile |
comfyui_yvann-nodes |
FloatsVisualizer (render a float array as a histogram image) |
comfyui-impact-pack |
Preview Bridge (Image) / Preview Bridge (Latent) — tee inspection while passing through |
comfyui-easy-use |
easy showAnything, easy showLoaderSettingsNames, imageCount, imagesCountInDirectory |
When to Use This Skill
| Use this skill when... | Use instead when... |
|---|---|
| Inspecting a value mid-graph without changing it (show/log/preview nodes) | Extracting metadata from a finished output file -> comfy-metadata |
| Checking VRAM/CPU/timing during a run | Computing the value being displayed -> comfy-math-strings |
Sources of truth
custom_nodes/comfyui-custom-scripts/py/show_text.py— pysssss ShowTextcustom_nodes/comfyui_essentials/misc.py— DisplayAny, ConsoleDebug, DebugTensorShapecustom_nodes/comfyui-kjnodes/nodes/nodes.py— VRAM_Debug, TimerNodeKJ, Sleep, Get*SizeAndCount, FastPreview, PreviewImageOrMaskcustom_nodes/ComfyUI-Crystools/crystools/nodes_*.py— CConsoleAny*, CUtilsStatSystem, metadata nodes
Show-this-value decision
| Value type | Best node | Why |
|---|---|---|
| STRING (short) | pysssss ShowText |
Renders in the node widget; auto-resizes; persists in workflow JSON |
| STRING (long / multiline) | bjornulf ShowStringText or pysssss ShowText |
Both wrap text; ShowText truncates after ~10 lines but expands on hover |
| ANY (don't know the type) | essentials DisplayAny or easy showAnything |
Coerces to STRING and renders |
| FLOAT / INT | bjornulf ShowFloat / ShowInt |
Specific formatters; cleaner display than DisplayAny |
| JSON / dict / list | bjornulf ShowJson or Crystools CConsoleAnyToJson |
Pretty-prints with indentation |
| Tensor (latent / image) shape | essentials DebugTensorShape |
Logs (B, C, H, W) to console; doesn't display in node UI |
| Float curve over a batch | yvann FloatsVisualizer |
Renders the array as a histogram image |
| Console log (no widget) | essentials ConsoleDebug, Crystools CConsoleAny, dream DreamStringToLog |
Output to server stdout/log only — invisible in editor; useful for batch jobs |
| Image (tee with passthrough) | impact Preview Bridge |
Pass-through + preview in one node — see the data, keep the chain |
| Image (just preview, no passthrough) | ComfyUI core PreviewImage or kjnodes PreviewImageOrMask |
The kjnodes variant auto-detects whether the input is image or mask |
Where the display goes
- Node-widget UI (visible in the workflow editor):
ShowText,ShowFloat,ShowInt,ShowStringText,ShowJson,DisplayAny,easy showAnything. These render INSIDE the node's body, expanding the node to fit the value. - Server log / console (
journalctl -u comfyui.serviceon this install):ConsoleDebug,DebugTensorShape,CConsoleAny,DreamStringToLog. No editor display — use these for batch jobs running headless viacomfy run. - On-disk log file:
DreamLogFileappends to a configurable file path; useful for cross-queue tracking. - Visible as image preview:
PreviewImageOrMask,FastPreview,FloatsVisualizer. The preview shows in the standard preview pane.
Counts and sizes
| Need | Node | Outputs |
|---|---|---|
| Image batch (B, H, W) | kjnodes GetImageSizeAndCount |
width, height, batch_count |
| Mask (B, H, W) | kjnodes GetMaskSizeAndCount |
width, height, batch_count |
| Latent (B, C, H, W) | kjnodes GetLatentSizeAndCount |
width, height, batch_count |
| Just N (batch size) | essentials BatchCount |
int |
| Image batch count (easy-use variant) | easy imageCount |
int |
| Count image files in a directory | easy imagesCountInDirectory |
int (with offset/limit) |
| Image file's metadata | bjornulf ImageDetails |
width, height, channels, format, mode |
| Video file's metadata | bjornulf VideoDetails |
width, height, fps, duration, codec |
Get*SizeAndCount is the canonical choice — it emits w/h/batch as
separate INTs that you can wire to math nodes or display.
System telemetry
For figuring out what's eating VRAM / CPU / RAM mid-graph:
| Node | What it reports | When called |
|---|---|---|
Crystools CUtilsStatSystem |
CPU %, RAM used/total, GPU VRAM used/total (per-card) | Re-polls every time its output is consumed |
kjnodes VRAM_Debug |
One-shot VRAM snapshot to console | When the node executes |
kjnodes TimerNodeKJ |
Wall-clock elapsed time between start/end of a section | When the end node executes |
kjnodes Sleep |
Pauses execution for N seconds (throttling, not telemetry) | When executed |
Per-section timing
┌─► TimerNodeKJ (start) ──────► (just a pass-through tag)
│
upstream value ─┤
│ (do stuff in between)
│
└─► TimerNodeKJ (end) ──► duration_seconds (FLOAT)
│
▼
bjornulf `ShowFloat`
or DreamFloatToLog
Wire the same TimerNodeKJ id on both sides — the node remembers the start timestamp keyed by its instance and emits a duration on the "end" port.
Preview Bridge and the ExecutionBlocker pitfall
Impact's Preview Bridge (Image) / Preview Bridge (Latent) are the
workhorse "see this and pass it through" nodes. Wire an image in,
get the same image out, plus a preview in the editor.
Critical pitfall: Preview Bridge silently consumes
ExecutionBlocker sentinels. If a path through the bridge gets
blocked upstream, the bridge:
- Shows nothing in the preview (no error, no indicator).
- Does NOT propagate the blocker downstream — it converts the blocked path into a "no-op pass-through" of nothing.
Consequence: if you tee Preview Bridge off a path that may be
blocked (e.g. behind an easy blocker), the downstream consumer of
the bridge's output silently sees a None — not a blocker — and
either errors with a type mismatch or proceeds with garbage.
Workaround: when blockers may appear in the path, use kjnodes
FastPreview downstream of the bridge — FastPreview passes
sentinels through correctly. Or branch the preview off BEFORE the
blocker, not after.
Metadata extraction
For lightweight in-graph metadata reads (read PNG-embedded workflow JSON during a workflow run):
| Node | Use |
|---|---|
Crystools CImageLoadWithMetadata |
Load image + emit its image.info PNG metadata as JSON |
Crystools CMetadataExtractor |
Pull a specific key from a metadata blob |
Crystools CMetadataCompare |
Diff two metadata blobs and report differences |
bjornulf ImageDetails |
Read width/height/format from any image — doesn't surface workflow JSON |
For batch / cross-output-directory analysis ("which prompt produced
all these images?", "scan output/ and find runs that used model X"),
use the dedicated comfy-metadata skill — it covers the full
range of metadata sources (PNG tEXt, WebP EXIF Make/Model, MP4
container, kijai WanVideoWrapper's comment blob, VHS metadata,
.latent safetensors) and the scripts/scanners for batch
inspection.
The Crystools nodes here are for inline metadata reads as part
of a workflow's logic; comfy-metadata is for offline analysis.
Counter-pattern: timing/profiling vs the wrong layer
If a workflow is slow and you want to find the slow node:
- ✅ Use
TimerNodeKJaround suspected sections. - ✅ Use
CUtilsStatSystemto log VRAM through the run. - ✅ Check the ComfyUI server log (
journalctl -u comfyui.service) — every node logs its execution time at the end of the run. - ❌ Don't add
Sleep"to give the GPU time" — it doesn't help, ComfyUI is synchronous within a queue.
For deep model-level profiling (CUDA timelines, sageattn vs flash
attention comparisons, kernel-level), this skill is the wrong layer
— consult the model-family skill (e.g. wan for radial sage
attention discussion).
Recipes
"Why is my prompt different from what I typed?"
After all wildcard expansion, LoRA trigger autoload, and string manipulation, you want to see the literal STRING that hits the text encoder:
(your full prompt-assembly chain)
│
▼
(output STRING)
│
┌────────┴────────┐
│ │
▼ ▼
CLIPTextEncode ShowText (pysssss)
The ShowText widget will display the resolved prompt — visible in
the editor after queue. Useful for catching wildcards that didn't
resolve (__styles__ remained literal because the file was
missing), or LoRA tags that came back empty.
Per-step time budget
You want to know how long each sampler in a 3-sampler chain takes:
LoadImage ─► TimerNodeKJ(start, id=t1) ─► Sampler#1 ─► TimerNodeKJ(end, id=t1) ─► dt1
│ │
│ ▼ DreamFloatToLog
│
└► TimerNodeKJ(start, id=t2) ─► Sampler#2 ─► …
Three Timer pairs, three durations logged. After the run, check
the server log or the DreamLogFile output for a per-sampler
breakdown.
VRAM watch during a long batch
LoadImage ──► CUtilsStatSystem ──► (continues to KSampler)
│
▼ (writes a line per-poll to log)
DreamStringToLog
CUtilsStatSystem polls VRAM on each evaluation. Wire its output
through a logger so each queue tick records GPU state — easy to
correlate OOMs with workflow position.
Surface batch counts before sampling
LoadImageBatchFromDir ──► IMAGE ───────► (downstream sampler)
│
▼
GetImageSizeAndCount ──► width / height / batch_count
│
▼
ShowInt
Before queuing a big batch, glance at the count to confirm you didn't accidentally load a directory of 500 images when you meant 5.
Gotchas
ShowTextupdates AFTER queue completion, not live during the run. For mid-run display you need a console log (DebugTensorShape,CConsoleAny) plus tailing the server log.Preview BridgeswallowsExecutionBlocker— see above. Mitigations: tee off the path BEFORE any potential blocker, or useFastPreviewdownstream.CUtilsStatSystemonly polls when its output is consumed. Wiring it to nothing means it never runs. Wire the output to a console logger or aShowFloatto make it actually poll.DisplayAnytruncates large strings to ~10 lines / ~1000 chars. For longer values useShowStringText(bjornulf) which scrolls, orDreamStringToLogwhich writes to the server log without truncation.TimerNodeKJstart/end pairing: theidparameter must match between the start and end instances. Multiple Timer pairs with the same id cross-pollute their start times.Sleepis on the graph execution thread, not GPU. It blocks the entire queue, including unrelated parallel branches. Use only when intentionally throttling.FloatsVisualizerrenders to image at fixed resolution — the output is an IMAGE, not a graph object. Wire it throughPreviewImageto display.DreamLogFileopens the file in append mode each call — for high-frequency logging in a loop, file IO becomes the bottleneck. Use a console logger instead and tail the server log offline.- Crystools metadata nodes operate on PNG
image.infoonly — they don't read MP4/WebP/EXIF. For those, the offlinecomfy-metadataskill covers the full range.
Cross-refs
comfy-math-strings— formatting numeric / string values before display (the math is in math-strings; the show is here).comfy-flow-control— Preview Bridge as a routing tee (flow-control's gotcha list also covers the blocker pitfall).comfy-metadata— deep metadata extraction across output directories: PNG tEXt / iTXt, WebP EXIF, MP4 container, kijai WanVideoWrapper / VHScommentblobs,.latentsafetensors. When the question is "what produced this output file?" (offline / retrospective), reach forcomfy-metadata. When the question is "what is this current image's PNG metadata?" (inline / live), use the Crystools nodes documented here.comfy-conditionals—easy showAnythingon a BOOLEAN to confirm a predicate at queue time before trusting the branch decision.
Things this skill does NOT cover
- Offline / batch metadata analysis — →
comfy-metadata. - Performance profiling at the model layer (sageattn vs flash,
KV cache, attention slicing) — → model-family skills (
wan,z-image). - Workflow-level reorganization to make a graph more debuggable
(auto-layout, group cohesion) — →
comfy-workflow-layout. - Computing the values being displayed — →
comfy-math-strings. - The
simplifyuser-level skill (review changed code) — that's a Claude Code agent skill, not a ComfyUI workflow skill.