List / Batch Count
Find Out Whether You're Holding a List or a Batch
- value
- count
- info
ComfyUI has two kinds of "more than one", and they look identical on the canvas. A list makes the downstream node run once per element. A batch is one tensor with an extra leading dimension, so the node runs once and gets everything at once. Four images as a list means four sampling passes; four as a batch means one. Both arrive through the same wire, and nothing on the canvas tells you which you've got.
That mismatch is behind a family of confusing bugs - a video workflow that outputs one frame, a detailer that only touches the first face in a lineup, a run that's mysteriously 8x slower. FVM_ListCount is the cheap answer: plug anything into it and it tells you what arrived, how many, and which kind.
What it actually reports
The verdict is one of four words: LIST (several separate items - the engine runs whatever comes next once per item), BATCH (one item internally carrying several things, so downstream runs once), SINGLE, or EMPTY (nothing arrived, unwired or bypassed).
It also names the type - IMAGE, MASK, LATENT, AUDIO, CONDITIONING, a plain STRING/INT/FLOAT - and the shape, which is where BATCH IMAGE (4 x 1024x1024x3) versus LIST of IMAGE (4 items) settles it.
How it works
The trick is one flag: INPUT_IS_LIST = True, which means don't unpack this for me. Normally ComfyUI sees a list coming in and calls your node once per element - convenient, and it means you can never observe the length. Opting out, FVM_ListCount receives the wrapper itself and counts it.
After that the logic is short. More than one element → LIST. Exactly one element whose leading dimension is bigger than 1 → BATCH. Nothing → EMPTY. The labelling walks whatever it was handed: a 4-D tensor ending in 1, 3 or 4 channels is an IMAGE (leading dim = frame count), 3-D is a MASK, a dict with samples is a LATENT, a dict with waveform is AUDIO.
The genuinely clever bit is CONDITIONING. A conditioning is already a Python list, of [tensor, dict] pairs. So one conditioning with two entries (what Combine or Concat produces) reports as count 2, while three separate conditionings report as a LIST of 3. Correct, and the thing that'll confuse you first: two conditioning entries are not two runs.
Inputs and outputs
There is one input, value, typed as the wildcard * and forced to a socket, so it takes literally anything and has no widget to type into. It's optional, and the node declares VALIDATE_INPUTS returning True so the backend skips type-checking a socket it can't reason about.
Two outputs. count is an INT you can wire into anything expecting a number - a comparison, a math node, a filename prefix, a seed. info is a STRING carrying the whole sentence (LIST of IMAGE (12 items) -> count 12), the one to send to a text or save node when you want the diagnosis in a log. The read-only box on the node face is that same sentence: UI, not a socket.
Installing it
ComfyUI Manager, search fvmtools, install, restart. By hand:
cd ComfyUI/custom_nodes
git clone https://github.com/ping1979ping/comfyui-FVMtools.git
The README's clone snippet still says your-username - don't paste that. Look under FVM Tools/Utils.
No models are needed for this node - the pack's requirements.txt is the heavy half of a face-detailing toolkit (insightface, onnxruntime-gpu, opencv-python, numpy), and counting needs none of it. Install them anyway: the pack registers everything inside one big try: block, and the face modules import cv2 and insightface at module level, so a missing dependency can knock out the whole node list, this utility included.
When it misbehaves
The node isn't in the menu. Check the console. That try block ends in except ImportError: pass, so a missing cv2 or insightface leaves the pack silently empty. Install the four requirements.
The text box is blank, or it says count 0. Blank is expected on a freshly opened workflow - the box fills on execution and isn't saved with the file. A zero means nothing is connected, or the upstream node is bypassed; an unwired optional input never reaches the node, and that's EMPTY, not an error.
Your 4-image batch still ran your sampler once. Correct, and now you know why. This node reports; it doesn't convert. If you wanted four runs, you need a batch-to-list step upstream.
On the Nodes 2.0 frontend the box may not draw or refresh. Any node whose readout is a custom JS widget is at the mercy of that rewrite, which has been breaking third-party rendering since late 2025. The count and info sockets are pure backend - wire them out and ignore the box.
This node only landed in the pack in October 2026, so the source is the only documentation - it's short enough to read in one sitting.
Inputs (1)
| Name | Type | Default | Description |
|---|---|---|---|
| valueopt | * | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| count | INT | — |
| info | STRING | — |