unslothai/unsloth · error · ValueError
guidance_start must be <= guidance_end
Error message
guidance_start must be <= guidance_end
What it means
Raised by a ControlNetSpec model_validator when guidance_start > guidance_end. Both are fractions in [0,1] of the denoise schedule; an inverted range would mean 'act over no steps', producing silently unguided output or a 500 deep in the denoise loop — rejected up front as a clean 422 instead.
Source
Thrown at studio/backend/models/inference.py:2924
control_type: str = Field(
"passthrough",
description = "How to derive the control map: 'passthrough' (already a map) or 'canny'",
)
strength: float = Field(
1.0, ge = 0.0, le = 2.0, description = "ControlNet conditioning scale; 0 disables"
)
guidance_start: float = Field(
0.0, ge = 0.0, le = 1.0, description = "Fraction of steps at which ControlNet begins"
)
guidance_end: float = Field(
1.0, ge = 0.0, le = 1.0, description = "Fraction of steps at which ControlNet ends"
)
@model_validator(mode = "after")
def _check_guidance_range(self) -> "ControlNetSpec":
# An inverted range means "act over no steps"; reject it as a clean 422 instead of a 500 deep in the denoise.
if self.guidance_start > self.guidance_end:
raise ValueError("guidance_start must be <= guidance_end")
return self
class DiffusionGenerateRequest(BaseModel):
"""Request to generate one image from the loaded diffusion model."""
prompt: str = Field(..., min_length = 1, description = "Text prompt")
negative_prompt: Optional[str] = Field(
None, description = "What to avoid (if the model supports it)"
)
width: int = Field(1024, ge = 256, le = 2048, description = "Image width in pixels (multiple of 16)")
height: int = Field(
1024, ge = 256, le = 2048, description = "Image height in pixels (multiple of 16)"
)
steps: int = Field(9, ge = 1, le = 100, description = "Number of denoising steps")
guidance: float = Field(0.0, ge = 0.0, le = 20.0, description = "Classifier-free guidance scale")
# le = 2**53-1: seeds round-trip through JSON recipes, where JavaScript rounds larger integers and a restored recipe would differ.
seed: Optional[int] = Field(View on GitHub (pinned to 203007d190)
Solutions
- Swap or clamp the values so guidance_start <= guidance_end.
- Enforce the ordering in the UI (when start moves past end, push end along).
- If you intended 'no guidance', omit the ControlNetSpec instead of an empty range.
Example fix
# before
controlnet = {"guidance_start": 0.8, "guidance_end": 0.2}
# after
start, end = sorted((0.8, 0.2))
controlnet = {"guidance_start": start, "guidance_end": end} Defensive patterns
Strategy: validation
Validate before calling
def clamp_controlnet(spec: dict) -> dict:
start, end = spec.get('guidance_start', 0.0), spec.get('guidance_end', 1.0)
if start > end:
start, end = end, start
return {**spec, 'guidance_start': start, 'guidance_end': end} Prevention
- Constrain UI sliders so start cannot cross end
- Order the pair (min, max) at request-build time
- Omit the ControlNetSpec entirely when no guidance is wanted
When it happens
Trigger: Sending controlnet: {"guidance_start": 0.8, "guidance_end": 0.2} with a diffusion generation request; commonly from swapping the two fields or from UI sliders that can cross.
Common situations: Two independent sliders for start/end where dragging one past the other is possible; configs authored with 'start when ControlNet ends' semantics reversed; copying examples from a tool that uses inverted notation.
Related errors
- ControlNet is not supported for the '{fam.name}' model famil
- {_cn_fs.reason}
- ControlNet currently combines with plain text-to-image only,
- ControlNet is not supported for this model/quantisation on t
- ControlNet '{spec_id}' is for {', '.join(entry.families)}, n
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/67cde11b129badd9.
Report an issue: GitHub.