KfDebug_Latent
The node you'll reach for when animation frames go weird
- item
- LATENT
Of all the KfDebug_* nodes, this is the one you'll actually reach for, because latent batch sizes are where this entire pack's workflows fall apart. A latent in ComfyUI is a dict holding a tensor under the key samples, shaped [B, C, H, W] - and when your prompt schedule produces 24 conditionings but your latent batch is 16 frames, nothing complains until the sampler quietly misbehaves. KfDebug_Latent shows you the batch size (and the channel/spatial dims) in your console, and passes the latent through untouched.
It's a passthrough, remember - the inspection lands in the terminal where ComfyUI runs, not on the canvas. That's the family trait, and it's the thing that confuses first-timers every time.
Why you'd reach for it
Frame-count mismatches. If you're doing prompt scheduling with KfGetScheduleConditionSlice (default n=24) and feeding the result into an AnimateDiff-style sampler running a different number of frames, the two batches have to agree. KfDebug_Latent on the latent wire tells you the real B - 16, 24, whatever - so you can reconcile it with your schedule's n before you sample, instead of after you render 60 frames of garbage.
It's also the fastest way to confirm a VAE encode actually produced a latent at all, and what spatial resolution it's sitting at. The H and W in the shape will out you if a resize or crop upstream did something you didn't expect.
The inputs that matter
item- theLATENTto inspect, force-input off a wire.label- multiline string, default"debugging passthrough". When your schedule, your latent, and your sampler all have debug nodes on them, distinct labels are the only way to tell the console lines apart. Label it"latent batch"and grep for that.
Output is a single LATENT - the identical dict, passed through unmodified, so you can drop this node into a live path without changing the graph's behavior.
How it works
The inspector logs the type, then since a latent is a dict it prints the keys (item.keys(): dict_keys(['samples'])) and recurses into the value. The samples tensor has both dtype and shape, so you get the full picture:
item.type: <class 'dict'>
item.keys(): dict_keys(['samples'])
item.dtype: torch.float32
item.shape: torch.Size([16, 4, 64, 64])
There's your batch of 16, your 4 latent channels, and a 64×64 latent space - everything you need to know whether this latent matches the conditioning it's about to be sampled with.
Installing it
Part of ComfyUI-Keyframed (dmarx's pack wrapping his keyframed library). ComfyUI Manager: search "Keyframed". Or manually:
cd ComfyUI/custom_nodes
git clone https://github.com/dmarx/ComfyUI-Keyframed
Restart ComfyUI. The pack pip-installs keyframed and toolz on first load and needs no model downloads.
Troubleshooting
No canvas output = check the terminal, as always. And if the batch size in the log disagrees with what you configured, work backwards: the debug node is a faithful passthrough, so the discrepancy is upstream - check your Empty Latent size or whatever node built the batch. One more thing worth knowing about this pack generally: its README admits curve division is broken upstream in keyframed, so if a latent-related curve value involves a divide, treat the result with suspicion.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| item | LATENT | — | |
| label | STRING | debugging passthrough | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| LATENT | LATENT | — |