{"record":{"id":"9044db3ad35886be","repo":"sgl-project/sglang","slug":"max-possible-layers-must-be-provided-alongside","errorCode":null,"errorMessage":"`max_possible_layers` must be provided alongside `select_layers`","messagePattern":"`max_possible_layers` must be provided alongside `select_layers`","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/srt/models/siglip2.py","lineNumber":391,"sourceCode":"        return hidden_states\n\n\ndef resolve_visual_encoder_outputs(\n    encoder_outputs: torch.Tensor | list[torch.Tensor],\n    post_layer_norm: Optional[nn.LayerNorm],\n    select_layers: Optional[list[int]] = None,\n    max_possible_layers: Optional[int] = None,\n) -> torch.Tensor:\n    \"\"\"Resolve outputs from visual encoder based on select_layers.\"\"\"\n    if select_layers is None:\n        if isinstance(encoder_outputs, list):\n            encoder_outputs = encoder_outputs[-1]\n        if post_layer_norm is not None:\n            encoder_outputs = post_layer_norm(encoder_outputs)\n        return encoder_outputs\n\n    if max_possible_layers is None:\n        raise ValueError(\n            \"`max_possible_layers` must be provided alongside `select_layers`\"\n        )\n\n    if not isinstance(encoder_outputs, list):\n        raise ValueError(\n            \"Expected encoder_outputs to be a list when select_layers is provided\"\n        )\n\n    # Get the hidden states corresponding to the layer indices\n    num_loaded_layers = len(encoder_outputs) - 1\n    offset = max_possible_layers - num_loaded_layers\n    hs_pool = [\n        (\n            encoder_outputs[layer_idx]\n            if layer_idx >= 0\n            else encoder_outputs[layer_idx + offset]\n        )\n        for layer_idx in select_layers","sourceCodeStart":373,"sourceCodeEnd":409,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/srt/models/siglip2.py#L373-L409","documentation":"resolve_visual_encoder_outputs supports selecting intermediate layer outputs via select_layers, but it needs max_possible_layers (the checkpoint's full layer count) to map selected indices onto the possibly-truncated encoder output list. Calling with select_layers but no max_possible_layers is an API misuse.","triggerScenarios":"Calling resolve_visual_encoder_outputs(select_layers=[...]) without passing max_possible_layers from python/sglang/srt/models/siglip2.py:391.","commonSituations":"Custom multimodal wrappers or forks that call this helper directly; upstream refactors where a caller was updated to pass select_layers but not the new max_possible_layers argument.","solutions":["Pass max_possible_layers=config.num_hidden_layers of the vision encoder alongside select_layers","If you don't need intermediate features, drop select_layers and take the final output","Update forked callers to the current helper signature"],"exampleFix":"# before\nouts = resolve_visual_encoder_outputs(enc_out, select_layers=[5, 17])\n# after\nouts = resolve_visual_encoder_outputs(\n    enc_out, select_layers=[5, 17],\n    max_possible_layers=config.num_hidden_layers)","handlingStrategy":"validation","validationCode":"if select_layers is not None:\n    assert max_possible_layers is not None, \"select_layers requires max_possible_layers\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Wrap helper calls in a thin adapter that fills required kwargs from config"],"tags":["siglip2","api-misuse","layer-selection"],"backgroundTag":"missing-required-argument","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}