π Read File
Get a prompt, a caption or a JSON blob off disk and into the graph
- Text
Two things in this ecosystem are stored as text files next to something else: captions in a training set (an image.png with an image.txt beside it) and workflow/prompt exports you've saved by hand. Read File is the node that pulls either one into a STRING socket, so a prompt can live in a file you edit in your real editor instead of in a widget you keep re-typing.
How it works
It opens the path as UTF-8 and reads the whole thing. If the bytes aren't valid UTF-8 it retries with errors="replace", which means a binary file won't throw - you get text with replacement characters in it. That's a deliberate choice and a slightly dangerous one: pointing this at a .safetensors won't fail loudly, it'll feed a megabyte of mojibake into your prompt. Read text files.
Unlike most of the pack's file nodes, this one fails loudly in the cases that matter: an empty path raises ValueError("File path cannot be empty.") and a missing file raises FileNotFoundError("File not found: <path>"). Both come back as a red node, not a silent empty string. That's the right call for a read - the alternative gives you an empty prompt and an image that looks like the model ignored you.
The whole file is loaded into memory. For a caption or a saved workflow that's nothing; for a very large log it's a bad idea.
The inputs and outputs that matter
One input, File Path - absolute, and the tooltip says so. One output, Text, the file's contents as a STRING.
That single output can go almost anywhere, which is the node's charm:
- into a Text Concatenate to compose a prompt with the file's contents as one channel
- into JSON Preview when the file is metadata you exported earlier
- into JSON Validate and then JSON Merge if you're rebuilding metadata from a saved blob
- into a CLIP Text Encode directly, so the positive prompt is a file on disk you edit between runs
The reverse pairing is the one people build for batch work: List Files hands you newline-separated paths, and each of those paths is exactly what this node wants on its input.
The absolute-path requirement isn't a stylistic preference. Relative paths resolve against ComfyUI's working directory, which is the folder main.py was launched from - for a portable Windows install that's the ComfyUI root, for a Docker container it's whatever the entrypoint set. Point at absolute paths and behaviour stops depending on how the process was started.
Because it's a plain STRING widget, the path itself can be wired: Path Join β Read File means the graph decides which file to read, and the same workflow reads a different caption per run.
How to install it
Part of Avaray/honda-nodes - ComfyUI Manager β Node Pack β search Honda Nodes β Install β restart. Manual:
cd ComfyUI/custom_nodes
git clone --depth 1 https://github.com/Avaray/honda-nodes.git
cd honda-nodes
python install.py
Stdlib only, so this node needs nothing from install.py - but the script is what downloads the jq and ime binaries the JSON and metadata nodes use. No pip packages, no models.
Common issues
File not found on a path you can see in your file browser. Three usual causes: a trailing space or newline in a wired path string (Path Normalize will strip and clean it), Windows-style separators on a Linux box (C:\data\x.txt is not a path there), or ComfyUI running in a container where the host's filesystem isn't mounted at the same place. ls the exact string from a shell inside the same environment before you debug anything else.
File path cannot be empty. The path widget is blank, or whatever feeds it produced an empty string. This one's a feature: it stops the run before it silently generates against nothing.
The prompt includes a weird character at the end. Your text file has a trailing newline and it's being faithfully passed along. Most encoders don't care; the JSON nodes will. Path Normalize won't help - trim it in the file, or through Text Replace.
A binary file gave you gibberish instead of an error. errors="replace" fallback. Only point this at text.
Editing the file doesn't change the output. ComfyUI cached the run because the path didn't change and it can't know a file's contents changed. Re-queue with a change somewhere upstream, or nudge a widget - the node has no IS_CHANGED watching file mtimes.
Inputs (1)
| Name | Type | Default | Description |
|---|---|---|---|
| file_path | STRING | Absolute path to the text file to read. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| Text | STRING | β |