# BUGS ## Open ### RM Styles Pipe: positive prompt missing from its slot in the pipe **Reported:** 2026-08-24 **Nodes:** RM Styles Pipe, RM Styles Pipe Out **Status:** Investigated — **the pipe position is correct**. The positive is being *rewritten in place* by the content policy, not misplaced or dropped. Awaiting confirmation that this is what was actually observed. **Symptom (as reported):** the styles pipe "no longer seems to be outputting the positive prompt where it's supposed to be in the pipe." **Known layout** — `RM_STYLES_PIPE` index 0 is Positive: `0 Positive · 1 Negative · 2 Motion · 3 ImageLoras · 4 MotionHigh · 5 MotionLow · 6 Number · 7 Name · 8 PolicyStatus` **Ruled out by measurement**, running the real node (Manual mode, `positive_mode=Off`): - Pipe is a 9-tuple; `[0] Positive` is populated. `RMStylesPipeOut` unpacks it to `[0] Positive` correctly. - All eight return paths in `RMStylesFull.load_style` — including `empty_result` and the free-prompt early return — emit an 8-tuple with positive at index 0. No ordering drift. - `js/rm_styles_overrides.js` only hides/disables widgets. It never adds or removes any, so the positional `widgets_values` mapping is intact. **Actual finding — the content policy rewrites most of the library.** Measured across all 293 styles (`THRESHOLD = 10`): | outcome | count | share | |---|---|---| | clean | 76 | 25.9% | | sanitized | 206 | 70.3% | | blocked | 11 | 3.8% | **74% of styles no longer emit their original positive.** No positive is ever left empty — blocked styles get `PLACEHOLDER_POSITIVE` instead, which is why this reads as "the wrong text" rather than "nothing". Of the sanitized ones: median 95% of the text survives, but the worst keep only 55% (e.g. #71 211→115 chars, #225 441→314, #83 243→178). **Open question:** is this the reported bug (policy too aggressive / firing where it shouldn't), or is something else being observed downstream? The 11 blocked styles are the most visible — they emit placeholder text with nothing of the original. **Curiosity, low priority:** `sanitize()` can *lengthen* a prompt (min delta −18 chars, max 104% kept). It rebuilds with `", ".join(kept)`, so a source using other separators comes back slightly longer. ### RM Styles: Random mode "picks the same styles over and over" **Reported:** 2026-08-20 **Nodes:** RM Styles Full, RM Styles Full (Display), RM Styles Pipe **Status:** Investigated — original hypothesis (number rounding) NOT confirmed. Two real issues found, neither is the rounding. **Original hypothesis:** the random prompt number is being rounded/manipulated into a narrow range. **Disproved.** There is no float math anywhere in the path. `_get_random_prompt()` uses `random.choice()` over a list of integer keys; the JS side (`js/rm_styles_full.js`) does no random math at all in Random mode. **Evidence — measured, not reasoned.** 602 real Random picks parsed out of `user/comfyui*.log`, compared against 600 simulated runs of the node's own algorithm: | metric | observed | simulated (correct picker) | |---|---|---| | max times any style picked (range 1–331, 321 draws) | 4 | 4 | | styles never picked | 77 | 86 | | per-style count variance | 0.781 | 0.891 | | min gap between repeats | 31 | 31 (= history size + 1) | Observed variance is slightly *below* random, i.e. the 30-item anti-repeat history is working and the spread is marginally more even than chance. **The picker is statistically sound.** Chart: `C:\Users\rober\Playground\style-frequency.html` **Real issue 1 — `minimum`/`maximum` widgets silently shrink the library.** `candidates = [n for n in available_numbers if minimum <= n <= maximum]` (`nodes/styles_full.py:65`). Recent sessions ran `minimum=150, maximum=330`, which makes **133 of 293 styles unreachable**. This is the actual cause of the perceived repetition — the pool really is smaller, the picker is just faithfully sampling it. Also note style `#999` is an outlier in `data/styles.json`; any `maximum` below 999 excludes it, and the next-highest real style is 331. **Real issue 2 (latent landmine) — the picker uses the *global* `random` module.** `random.choice()` at `nodes/styles_full.py:76` shares Python's process-wide RNG. Many ComfyUI packs call `random.seed(seed)` while they run (ComfyUI-Easy-Use's seed/wildcard nodes, comfyui-frame-interpolation, ComfyUI-Hunyuan3DWrapper, basic_data_handling — Easy-Use's own `py/server.py:5` carries a comment acknowledging this). If any such node reseeds with a **fixed** seed before the styles node executes, `random.choice()` returns the same index every run and the anti-repeat history turns the picker into a closed deterministic cycle of exactly `RANDOM_HISTORY_SIZE + 1 = 31` styles. Reproduced: ``` distinct styles seen in 200 runs: 31 cycle: [232,233,234,235,236,237,238,240,...,268, 232,233,234,235,...] # repeats forever ``` That is *precisely* the reported symptom. It is not currently firing in the saved workflows (none of them contain a reseeding node upstream), but it is one node away. **Fix:** give the picker its own RNG — `_RNG = random.Random()` at module level, then `_RNG.choice(...)` / `_RNG.randint(...)`. Immune to anything another pack does. **Real issue 3 (minor) — "closest match" fallback silently reuses styles.** `nodes/styles_full.py:245-248` snaps an unknown number to the nearest existing style. The numbering has ~30 gaps (e.g. 42, 45, 48, 53 missing; nothing between 332 and 998), so in Manual/Increment/Decrement modes a number landing in a gap silently repeats a neighbouring style instead of erroring or skipping. Does not affect Random mode, where the number is always drawn from existing keys. ## Resolved ### RM Styles: custom_json_path ignores quoted / relative / variable paths **Reported:** 2026-08-07 **Nodes:** RM Styles Full, RM Styles Full (Display), RM Styles Pipe, Styles Editor modal **Symptom:** Setting `custom_json_path` on an RM Styles node silently fell back to the bundled `data/styles.json`, or logged `Styles file not found` for a file that exists. **Evidence** (`user/comfyui.log`, 2026-08-07 09:40–09:43): ``` [RMStylesFull] Styles file not found: "C:\Users\rober\Documents\ComfyUI\ComfyUI\styles\Styles.csv" ``` The surrounding double quotes are part of the widget value — the log f-string adds none. That file exists on disk. **Root cause:** The path string from the free-text widget was passed straight to `Path()`. `custom_json_path.strip()` removes whitespace only, so: - Windows Explorer "Copy as path" quotes (`"C:\..."`) became part of the filename - `~` and `%USERPROFILE%` were never expanded - Relative paths resolved against ComfyUI's process CWD, not a predictable root The node loader (`_load_styles`) and the editor API (`_resolve_styles_file`) each did their own ad-hoc resolution, so they could also disagree about which file was being targeted. **Fix:** Single shared `_normalize_styles_path()` in `nodes/styles_full.py`, used by both the node loader and every editor API route. It strips whitespace, strips matched surrounding quotes, expands `~` and environment variables, and resolves relative paths against the ComfyUI base directory. Load failures now log the raw widget value alongside the resolved path so a mismatch is visible. **Note:** `.csv` styles files are still unsupported — the loader is JSON-only. A CSV path now resolves correctly but fails at parse time with an explicit message.