Skip to content

Fix nan sigmas when num_inference_steps=1 with shift_terminal - #14572

Open
promptsmith1990 wants to merge 1 commit into
huggingface:mainfrom
promptsmith1990:fix/flow-shift-terminal-single-step
Open

Fix nan sigmas when num_inference_steps=1 with shift_terminal#14572
promptsmith1990 wants to merge 1 commit into
huggingface:mainfrom
promptsmith1990:fix/flow-shift-terminal-single-step

Conversation

@promptsmith1990

Copy link
Copy Markdown

What does this PR do?

Fixes #14411.

FlowMatchEulerDiscreteScheduler.stretch_shift_to_terminal computes one_minus_z[-1] / scale_factor, where scale_factor is itself derived from one_minus_z[-1]. With num_inference_steps=1 the single sigma in the schedule is both the first and last point, and before any terminal stretching it is exactly 1.0 (pure noise), so one_minus_z[-1] is 0 and the division degenerates to 0/0, producing nan sigmas and timesteps. Any pipeline configured with shift_terminal (LTX, LTX2, ...) run with a single denoising step hits this.

While investigating, I found the same unguarded if self.config.shift_terminal: call-site pattern copy-pasted into two other schedulers that share the identical stretch_shift_to_terminal implementation — UniPCMultistepScheduler's use_flow_sigmas branch, and FlowMatchLCMScheduler — and both reproduce the same nan crash under the same conditions, so this PR fixes all three call sites the same way: skip the stretch when there's only one point in the schedule to stretch. Multi-step schedules are unaffected and still terminate at shift_terminal as before (covered by a regression test).

Testing

pytest tests/schedulers/test_scheduler_flow_match_euler_discrete.py -v
pytest tests/schedulers/test_scheduler_unipc.py -k flow_sigmas_single_step -v

FlowMatchEulerDiscreteScheduler had no dedicated test file at all despite being used across ~20 pipeline test files, so I added tests/schedulers/test_scheduler_flow_match_euler_discrete.py covering: multi-step still reaches shift_terminal (regression guard against the fix disabling stretching generally), single-step no longer produces nan sigmas/timesteps, and a single scheduler.step() call runs to completion without nan output. A matching regression test was added to test_scheduler_unipc.py for the use_flow_sigmas branch.

Also ran utils/check_copies.py and ruff check/ruff format on the changed files (clean) to confirm the stretch_shift_to_terminal # Copied from block itself was left untouched — only the calling guard changed at each site.

Before submitting

AI disclosure

This PR was prepared with AI assistance (Claude Code). The assistant found the bug while investigating issue #14411, traced the same defect into the two other schedulers, wrote the fix and tests, and ran the verification shown above. I (the human submitter) reviewed the diff and the verification output before submitting, and take responsibility for this contribution.

Self-review notes (against .ai/references/review-rules.md)

Blocking issues: none found.

Non-blocking (left for actual review): the new test_scheduler_flow_match_euler_discrete.py uses a plain unittest.TestCase rather than SchedulerCommonTest, since this scheduler currently has no dedicated test file at all and adopting the full common-test harness (dummy sample generation, forward-pass parity checks, etc.) for the first time here is a separate, larger effort than this bug fix.

Verdict: READY.

Who can review?

@yiyixuxu @dg845 — schedulers

@github-actions github-actions Bot added size/M PR with diff < 200 LOC fixes-issue tests schedulers and removed size/M PR with diff < 200 LOC fixes-issue labels Aug 23, 2026
FlowMatchEulerDiscreteScheduler.stretch_shift_to_terminal computes
one_minus_z[-1] / scale_factor, where scale_factor is itself derived
from one_minus_z[-1]. With num_inference_steps=1 the single sigma in
the schedule is both the first and last point, and before any terminal
stretching it is exactly 1.0 (pure noise), so one_minus_z[-1] is 0 and
the division degenerates to 0/0, producing nan sigmas and timesteps.
Any pipeline configured with shift_terminal (LTX, LTX2, ...) that is
run with a single denoising step hits this.

The same unguarded `if self.config.shift_terminal:` call-site pattern
was copy-pasted into two other schedulers that share the identical
stretch_shift_to_terminal implementation, UniPCMultistepScheduler's
use_flow_sigmas branch and FlowMatchLCMScheduler, and both reproduce
the same nan crash under the same conditions.

Fixes this by skipping the stretch when there is only one point in the
schedule to stretch, in all three call sites. Multi-step schedules are
unaffected and still terminate at shift_terminal as before.

Fixes huggingface#14411

Test Plan:

    pytest tests/schedulers/test_scheduler_flow_match_euler_discrete.py -v
    pytest tests/schedulers/test_scheduler_unipc.py -k flow_sigmas_single_step -v

New test_scheduler_flow_match_euler_discrete.py covers: multi-step
still reaches shift_terminal (regression guard), single-step no longer
produces nan sigmas/timesteps, and a single scheduler.step() call runs
to completion without nan output. A matching regression test was added
to test_scheduler_unipc.py for the use_flow_sigmas branch. Also ran
utils/check_copies.py and ruff check/format on the changed files
(clean) to make sure the stretch_shift_to_terminal "# Copied from"
block itself was left untouched.

This PR was prepared with AI assistance (Claude Code): the assistant
found the bug while investigating issue huggingface#14411, traced the same defect
into the two other schedulers, wrote the fix and tests, and ran the
verification above. I reviewed the diff and the verification output
before submitting.

Self-review (against .ai/references/review-rules.md): no blocking
issues found. One scope note left for the actual review: the new
test_scheduler_flow_match_euler_discrete.py uses a plain
unittest.TestCase rather than SchedulerCommonTest, since
FlowMatchEulerDiscreteScheduler currently has no dedicated test file
at all and adopting the full common-test harness (dummy sample
generation, forward-pass parity checks, etc.) for the first time is a
separate, larger effort than this bug fix.
@promptsmith1990
promptsmith1990 force-pushed the fix/flow-shift-terminal-single-step branch from 629de55 to 83e0624 Compare August 23, 2026 18:43
@github-actions github-actions Bot added size/M PR with diff < 200 LOC fixes-issue labels Aug 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Division by 0 bug when only one denoising step

1 participant