Pipe slot 0 is populated and RMStylesPipeOut unpacks it correctly; all eight return paths emit an 8-tuple with positive at index 0. The content policy is rewriting the text in place instead: across 293 styles, 26% clean / 70% sanitized / 4% blocked. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012uM7Ru1JYn48n6c5Rzwd99
141 lines
7.3 KiB
Markdown
141 lines
7.3 KiB
Markdown
# 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.
|