Worker rejects restyle-into-preset (empty prompt + style) — empty-prompt guard runs before prompt.Apply #14

Closed
opened 2026-06-06 16:00:08 +00:00 by mAi · 2 comments
Collaborator

Severity: live-breaking (restyle's canonical path)

Found by a live smoke restyle right after #13 shipped. A job with prompt="" + style="watercolor" + init_image_id (exactly what flexsiebels' restyle UI sends when you pick a preset and type nothing) is rejected by the worker:

worker: job af0acd13... failed: job af0acd13...: empty prompt

Root cause

cmd/imagen/worker.go:225 guards on the RAW job prompt:

if job.Prompt == "" {
    return worker.Outcome{Err: fmt.Errorf("job %s: empty prompt", job.ID)}
}

but the style preset isn't folded into the prompt until line 238:

finalPrompt, err := prompt.Apply(job.Prompt, job.Style)

prompt.Apply("", "watercolor") correctly returns the watercolor suffix (see internal/prompt/prompt.go:60 — empty prompt + style => suffix becomes the prompt). The CLI does it in the right order (generate.go applies first); the worker checks first. So the empty-prompt-plus-style restyle — the primary case — dies before the style can become the prompt.

Fix

Move the empty check to AFTER prompt.Apply and test the RESULT:

  • Remove the if job.Prompt == "" early guard.
  • After finalPrompt, err := prompt.Apply(...), add: if strings.TrimSpace(finalPrompt) == "" { return worker.Outcome{Err: fmt.Errorf("job %s: empty prompt (no prompt and no style)", job.ID)} }.

Result: empty prompt + style => OK (canonical restyle); empty prompt + empty style => still rejected; this matches the CLI exactly.

Tests

  • worker pipeline test: empty prompt + valid style => Run proceeds (finalPrompt == style suffix), does NOT fail with empty-prompt.
  • empty prompt + empty style => still fails with the empty-prompt error.
  • Keep the existing non-empty-prompt path green.

Refs

  • Regression in #13 (img2img through the jobs queue). flexsiebels UI is correct — it sends empty prompt + style for a preset restyle; backend was wrong.
  • Closes the gap #12's live smoke was meant to catch.
## Severity: live-breaking (restyle's canonical path) Found by a live smoke restyle right after #13 shipped. A job with `prompt=""` + `style="watercolor"` + `init_image_id` (exactly what flexsiebels' restyle UI sends when you pick a preset and type nothing) is rejected by the worker: ``` worker: job af0acd13... failed: job af0acd13...: empty prompt ``` ## Root cause `cmd/imagen/worker.go:225` guards on the RAW job prompt: ```go if job.Prompt == "" { return worker.Outcome{Err: fmt.Errorf("job %s: empty prompt", job.ID)} } ``` but the style preset isn't folded into the prompt until line 238: ```go finalPrompt, err := prompt.Apply(job.Prompt, job.Style) ``` `prompt.Apply("", "watercolor")` correctly returns the watercolor suffix (see internal/prompt/prompt.go:60 — empty prompt + style => suffix becomes the prompt). The CLI does it in the right order (generate.go applies first); the worker checks first. So the empty-prompt-plus-style restyle — the primary case — dies before the style can become the prompt. ## Fix Move the empty check to AFTER `prompt.Apply` and test the RESULT: - Remove the `if job.Prompt == ""` early guard. - After `finalPrompt, err := prompt.Apply(...)`, add: `if strings.TrimSpace(finalPrompt) == "" { return worker.Outcome{Err: fmt.Errorf("job %s: empty prompt (no prompt and no style)", job.ID)} }`. Result: empty prompt + style => OK (canonical restyle); empty prompt + empty style => still rejected; this matches the CLI exactly. ## Tests - `worker` pipeline test: empty prompt + valid style => Run proceeds (finalPrompt == style suffix), does NOT fail with empty-prompt. - empty prompt + empty style => still fails with the empty-prompt error. - Keep the existing non-empty-prompt path green. ## Refs - Regression in #13 (img2img through the jobs queue). flexsiebels UI is correct — it sends empty prompt + style for a preset restyle; backend was wrong. - Closes the gap #12's live smoke was meant to catch.
Author
Collaborator

shift-1 — fix landed

Commit: 1f3e163 on mai/hotfix/hotfix-worker-rejects

Root cause confirmed exactly as described: cmd/imagen/worker.go guarded on the raw job.Prompt before prompt.Apply folded the style preset in (line 238), so a preset-only restyle (prompt="" + style="watercolor") died with empty prompt before the style could become the prompt. The CLI (generate.go) applies first, then names off the result — the worker checked first. Mismatch fixed.

Fix:

  • Removed the if job.Prompt == "" early guard.
  • After finalPrompt, err := prompt.Apply(job.Prompt, job.Style) added if strings.TrimSpace(finalPrompt) == "" { return ...empty prompt (no prompt and no style)... }.
  • Now mirrors the CLI ordering exactly.

Regression tests (cmd/imagen/worker_emptyprompt_test.go, via a recording test backend):

  • empty prompt + watercolor => Run proceeds, backend receives the folded style suffix as the prompt (no empty-prompt error).
  • empty prompt + empty style => still fails with the empty-prompt error, Generate never reached.
  • non-empty prompt => passes through verbatim, stays green.

go build ./..., go vet ./..., go test ./... all clean (incl. -race -count=2 on the new tests). Per house rules I do not close the issue — head merges and m closes. Setting work as done on my side.

Refs #14, #13.

### shift-1 — fix landed **Commit:** [`1f3e163`](https://mgit.msbls.de/m/ImaGen/commit/1f3e163) on `mai/hotfix/hotfix-worker-rejects` Root cause confirmed exactly as described: `cmd/imagen/worker.go` guarded on the **raw** `job.Prompt` before `prompt.Apply` folded the style preset in (line 238), so a preset-only restyle (`prompt=""` + `style="watercolor"`) died with `empty prompt` before the style could become the prompt. The CLI (`generate.go`) applies first, then names off the result — the worker checked first. Mismatch fixed. **Fix:** - Removed the `if job.Prompt == ""` early guard. - After `finalPrompt, err := prompt.Apply(job.Prompt, job.Style)` added `if strings.TrimSpace(finalPrompt) == "" { return ...empty prompt (no prompt and no style)... }`. - Now mirrors the CLI ordering exactly. **Regression tests** (`cmd/imagen/worker_emptyprompt_test.go`, via a recording test backend): - empty prompt + `watercolor` => Run proceeds, backend receives the folded style suffix as the prompt (no empty-prompt error). - empty prompt + empty style => still fails with the empty-prompt error, Generate never reached. - non-empty prompt => passes through verbatim, stays green. `go build ./...`, `go vet ./...`, `go test ./...` all clean (incl. `-race -count=2` on the new tests). Per house rules I do **not** close the issue — head merges and m closes. Setting work as done on my side. Refs #14, #13.
m closed this issue 2026-06-06 16:14:14 +00:00
Author
Collaborator

Fixed + merged to main (a5b5fed), worker rebuilt + redeployed. Verified the fix end-to-end: a preset-only restyle job (empty prompt + style=watercolor + init_image_id) now passes the prompt guard, the worker builds the img2img workflow, fetches the source image from Storage, and ComfyUI accepts the graph (executes all loaders + the source VAEEncode).

The smoke restyle did not produce an image, but for an environmental reason, not a code one: ComfyUI hit torch.OutOfMemoryError at the KSampler — mRock's GPU was at 15.8/16 GB (ollama 5.7G + mVoice 2.6G + whisper 2.0G + a running game 2.5G), leaving no room for FLUX to load. Nothing would generate in that state, txt2img included. So the restyle pipeline is correct; live verification (the pending part of #12) is gated on GPU headroom on mRock. This is the GPU-contention case mGPUmanager is meant to arbitrate.

Fixed + merged to main (`a5b5fed`), worker rebuilt + redeployed. Verified the fix end-to-end: a preset-only restyle job (empty prompt + `style=watercolor` + `init_image_id`) now passes the prompt guard, the worker builds the img2img workflow, fetches the source image from Storage, and ComfyUI accepts the graph (executes all loaders + the source VAEEncode). The smoke restyle did not produce an image, but for an **environmental** reason, not a code one: ComfyUI hit `torch.OutOfMemoryError` at the KSampler — mRock's GPU was at 15.8/16 GB (ollama 5.7G + mVoice 2.6G + whisper 2.0G + a running game 2.5G), leaving no room for FLUX to load. Nothing would generate in that state, txt2img included. So the restyle pipeline is correct; live verification (the pending part of #12) is gated on GPU headroom on mRock. This is the GPU-contention case mGPUmanager is meant to arbitrate.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: m/ImaGen#14
No description provided.