sgl-project/sglang · error · ValueError
Invalid direction: {direction}
Error message
Invalid direction: {direction} What it means
apply_conditional_control routes conditioning between the audio and vision towers based on a direction string ('a2v' or 'v2a'); any other string falls through to the else and raises. It is called from forward, so a bad direction surfaces at inference time, not init.
Source
Thrown at python/sglang/multimodal_gen/runtime/models/bridges/mova_dual_tower.py:607
primary_hidden_states: torch.Tensor,
condition_hidden_states: torch.Tensor,
x_freqs: Optional[Tuple[torch.Tensor, torch.Tensor]] = None,
y_freqs: Optional[Tuple[torch.Tensor, torch.Tensor]] = None,
condition_scale: Optional[float] = None,
video_grid_size: Optional[Tuple[int, int, int]] = None,
) -> torch.Tensor:
"""Applies conditional control at the DiT hidden states level."""
if not self.controller.should_interact(
layer_idx, direction, self.interaction_mapping
):
return primary_hidden_states
if direction == "a2v":
conditioner = self.audio_to_video_conditioners[str(layer_idx)]
elif direction == "v2a":
conditioner = self.video_to_audio_conditioners[str(layer_idx)]
else:
raise ValueError(f"Invalid direction: {direction}")
conditioned_features = conditioner(
x=primary_hidden_states,
y=condition_hidden_states,
x_freqs=x_freqs,
y_freqs=y_freqs,
video_grid_size=video_grid_size,
)
if self.trainable_condition_scale and condition_scale is not None:
logger.warning(
"The current model has a trainable condition_scale, but condition_scale "
"was passed externally. Ignoring the trainable condition_scale and "
"using the external condition_scale=%s.",
condition_scale,
)
scale = condition_scale if condition_scale is not None else self.condition_scaleView on GitHub (pinned to 0132848349)
Solutions
- Set direction to exactly 'a2v' or 'v2v'-style supported values — check the elif chain: 'a2v' or 'v2a'
- Validate/normalize direction (lowercase, strip) before calling forward
- Type it as Literal['a2v','v2a'] in your calling code so mistakes surface at type-check time
- If you need a new mode, extend apply_conditional_control rather than passing an unknown string
Example fix
# before out = tower(hidden_states, direction=cfg.mode) # cfg.mode == "both" # after from typing import Literal mode: Literal["a2v", "v2a"] = "a2v" out = tower(hidden_states, direction=mode)
Defensive patterns
Strategy: type-guard
Validate before calling
direction = direction.strip().lower()
assert direction in ("a2v", "v2a"), f"invalid direction: {direction}" Type guard
from typing import Literal
Direction = Literal["a2v", "v2a"]
def is_direction(d: str) -> bool:
return d in ("a2v", "v2a") Try / catch
try:
out = tower(hidden_states, direction=direction)
except ValueError as e:
if "Invalid direction" in str(e):
direction = "a2v" # safe default
out = tower(hidden_states, direction=direction)
else:
raise Prevention
- Type direction fields as Literal['a2v','v2a'] in configs and function signatures
- Normalize strings (strip/lower) at the config boundary
When it happens
Trigger: Calling forward on the dual tower (or apply_conditional_control directly) with direction set to something like 'both', 'av', 'A2V', or an unset/None variable.
Common situations: A config field that defaults to a sentinel value; string interpolation building the direction dynamically and producing an empty or malformed value; new feature branches adding bidirectional conditioning without extending this router.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Unknown interaction strategy: {strategy}
- Invalid filter_apply_order: {filter_apply_order}
- Invalid join mode: {mode}
- Invalid mode: {mode}, must be one of 'write', 'read', 'skip'
- Unknown mode {mode!r}
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/814e17bbdaf80a8b.
Report an issue: GitHub.