sgl-project/sglang · error · ValueError
Cosmos3 action_horizon must be divisible by 4 so num_frames
Error message
Cosmos3 action_horizon must be divisible by 4 so num_frames is compatible with the temporal VAE
What it means
Cosmos3's temporal VAE downsamples time by 4, so the action horizon (num_frames - 1) must be divisible by 4. After resolving num_frames (from action_horizon or directly), the endpoint checks (num_frames - 1) % 4 == 0 and rejects otherwise. Valid num_frames are 5, 9, 13, 17, ... (horizons 4, 8, 12, 16, ...).
Source
Thrown at python/sglang/multimodal_gen/runtime/entrypoints/action/cosmos3.py:166
if action_horizon is None and num_frames is None:
action_horizon = 16
if action_horizon is not None:
action_horizon = int(action_horizon)
if action_horizon <= 0:
raise ValueError("action_horizon must be a positive integer")
expected_num_frames = action_horizon + 1
if num_frames is not None and int(num_frames) != expected_num_frames:
raise ValueError(
"Cosmos3 requires num_frames == action_horizon + 1, got "
f"num_frames={num_frames}, action_horizon={action_horizon}"
)
num_frames = expected_num_frames
else:
num_frames = int(num_frames)
if num_frames <= 1:
raise ValueError("Cosmos3 action num_frames must be greater than 1")
if (num_frames - 1) % 4 != 0:
raise ValueError(
"Cosmos3 action_horizon must be divisible by 4 so num_frames "
"is compatible with the temporal VAE"
)
images = _images_from_observation(observation)
video_path = options.get("video_path") or observation.get("video")
if action_mode == "policy" and not images:
raise ValueError("Cosmos3 policy input requires an observation image")
if action_mode == "inverse_dynamics" and video_path is None:
raise ValueError("Cosmos3 inverse_dynamics input requires an observation video")
if images and video_path is not None:
raise ValueError("Cosmos3 action requests accept either an image or a video")
batch_size = len(images) if images else 1
max_batch_size = max(1, int(getattr(server_args, "batching_max_size", 1)))
if batch_size > max_batch_size:
raise ValueError(
f"Cosmos3 action batch size {batch_size} exceeds "
f"--batching-max-size={max_batch_size}"View on GitHub (pinned to 0132848349)
Solutions
- Round action_horizon to the nearest multiple of 4 (default 16 → num_frames 17)
- If you need a different effective horizon, generate the nearest larger multiple of 4 and slice the returned actions to your desired length
Example fix
# before
{"parameters": {"action_horizon": 10}}
# after
{"parameters": {"action_horizon": 12}} Defensive patterns
Strategy: validation
Validate before calling
nf = int(params.get('num_frames', int(params.get('action_horizon', 16)) + 1))
assert (nf - 1) % 4 == 0, 'action_horizon must be divisible by 4' Prevention
- Snap horizons to multiples of 4 client-side: h = max(4, round(h/4)*4)
- Slice returned action chunks to the exact length your controller needs
When it happens
Trigger: action_horizon=10 (num_frames=11); num_frames=20 — any value where (num_frames-1) % 4 != 0.
Common situations: Tuning horizon to an arbitrary control-loop length (e.g. 10 Hz robot with 1s chunk); porting configs from models without temporal VAE constraints.
Related errors
- action_horizon must be a positive integer
- Cosmos3 requires num_frames == action_horizon + 1, got num_f
- world_size must be positive and divide global_heads
- Invalid spatial patching for packed token latents. Expected
- Cosmos3 action input accepts one image field; use a list or
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/e5a54e3521bfa9e3.
Report an issue: GitHub.