Files
Moser9815andClaude Opus 5 e413e41ac6 BUGS: styles pipe positive prompt - measured, position is correct
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
2026-08-24 17:06:28 -04:00

141 lines
7.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.