sgl-project/sglang · critical · ValueError

MiniMax H3 Qwen3-VL language-layer configuration is inconsis

Error message

MiniMax H3 Qwen3-VL language-layer configuration is inconsistent: {selected_layer} vs {int(arch.num_hidden_layers)}

What it means

The model requires arch.num_hidden_layers and arch.text_config.num_hidden_layers to agree (and be positive) after the tap-based truncation. Disagreement means the config was mutated inconsistently between the top-level and text config.

Source

Thrown at python/sglang/multimodal_gen/runtime/models/encoders/minimax_h3_qwen3vl.py:270

                f"encoder's {int(arch.checkpoint_num_hidden_layers)} layers"
            )
        arch.conditioning_projection_path = projection_path
        arch.num_hidden_layers = tap
        arch.text_config.num_hidden_layers = tap

    def should_materialize_checkpoint_weight(self, name: str) -> bool:
        name = _map_checkpoint_name(name)
        return (
            "rotary_emb.inv_freq" not in name
            and not _is_unconsumed_checkpoint_weight(name, self.selected_lm_layer)
        )

    def __init__(self, config: MiniMaxH3Qwen3VLConfig) -> None:
        super().__init__(config)
        arch = config.arch_config
        selected_layer = int(arch.text_config.num_hidden_layers)
        if selected_layer <= 0 or int(arch.num_hidden_layers) != selected_layer:
            raise ValueError(
                "MiniMax H3 Qwen3-VL language-layer configuration is "
                f"inconsistent: {selected_layer} vs {int(arch.num_hidden_layers)}"
            )
        self.model = Qwen3VLModel(
            arch,
            quant_config=config.quant_config,
            use_tensor_parallel=True,
            prefix="model",
        )
        # H3 and ClipProj consume an unnormalized intermediate residual stream.
        self.model.language_model.norm = nn.Identity()
        self.image_token_id = int(arch.image_token_id)
        self.video_token_id = int(arch.video_token_id)
        self.selected_lm_layer = selected_layer
        self.hidden_dim = MINIMAX_H3_QWEN3VL_HIDDEN_DIM
        self.conditioning_projection = (
            MiniMaxH3ConditioningProjection(arch.conditioning_projection_path)
            if arch.conditioning_projection_path is not None

View on GitHub (pinned to 0132848349)

Solutions

  1. Set both arch_config.num_hidden_layers and arch_config.text_config.num_hidden_layers to the same positive value
  2. If truncating layers via the conditioning-projection tap path, rely on configure_component_paths which sets both consistently

Example fix

# before
arch.num_hidden_layers = 12
arch.text_config.num_hidden_layers = 28
model = MiniMaxH3Qwen3VLModel(config)
# after
arch.num_hidden_layers = 12
arch.text_config.num_hidden_layers = 12
model = MiniMaxH3Qwen3VLModel(config)
Defensive patterns

Strategy: validation

Validate before calling

assert 0 < arch.text_config.num_hidden_layers == arch.num_hidden_layers

Prevention

When it happens

Trigger: Constructing MiniMaxH3Qwen3VLModel with arch_config where num_hidden_layers != text_config.num_hidden_layers or text_config.num_hidden_layers <= 0.

Common situations: Manually editing config to limit layers (e.g. layer offloading / truncation experiments) and updating only one of the two fields; a config-loading bug that sets them differently.

Related errors


AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28). Data as JSON: /api/errors/3b2d85c401c1d5ae. Report an issue: GitHub.