{"record":{"id":"b08318bc2360b4f2","repo":"sgl-project/sglang","slug":"keyframe-resolved-frame-index-values-disagree-with","errorCode":null,"errorMessage":"keyframe resolved_frame_index values disagree with semantic anchors: expected {expected_pixels!r}, got {resolved_pixels!r}","messagePattern":"keyframe resolved_frame_index values disagree with semantic anchors: expected (.+?), got (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/minimax_h3/canvas.py","lineNumber":135,"sourceCode":"            \"keyframe target-canvas materials require plan.task='fl2va' or 'ref2va'\"\n        )\n    semantic_indices = tuple(material.frame_index for material in keyframes)\n    if semantic_indices not in MINIMAX_H3_FL2VA_KEYFRAME_SIGNATURES:\n        raise ValueError(\n            \"MiniMax H3 keyframes must use one of the ordered frame_index signatures \"\n            f\"{MINIMAX_H3_FL2VA_KEYFRAME_SIGNATURES!r}, got {semantic_indices!r}\"\n        )\n    frame_count = plan.shape.get(\"frame_count\")\n    if isinstance(frame_count, bool) or not isinstance(frame_count, int):\n        raise ValueError(\"keyframe preparation requires an integer frame_count\")\n    if frame_count <= 1:\n        raise ValueError(\"keyframe preparation requires frame_count > 1\")\n    expected_pixels = tuple(\n        frame_count - 1 if index == -1 else index for index in semantic_indices\n    )\n    resolved_pixels = tuple(material.resolved_frame_index for material in keyframes)\n    if resolved_pixels != expected_pixels:\n        raise ValueError(\n            \"keyframe resolved_frame_index values disagree with semantic \"\n            f\"anchors: expected {expected_pixels!r}, got {resolved_pixels!r}\"\n        )\n    return semantic_indices\n\n\ndef minimax_h3_prepared_keyframes(batch: Any, plan: Any) -> dict[str, Any]:\n    \"\"\"Resolve + prepare one or two first/last keyframes once per request.\n\n    The target canvas is shared across keyframes and must already be frozen by\n    the pre-queue probe/resolve hook.\n    Top-level ``image`` / ``canvas_width`` / ``canvas_height`` keys mirror the\n    first-keyframe payload for compatibility; per-keyframe entries live under\n    ``images``.\n    \"\"\"\n    keyframes = _keyframe_materials(plan)\n    semantic_indices = _validate_keyframe_materials(plan, keyframes)\n    cached = batch.extra.get(MINIMAX_H3_PREPARED_KEYFRAMES_EXTRA_KEY)","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/minimax_h3/canvas.py#L117-L153","documentation":"During MiniMax-H3 keyframe preparation, each keyframe material carries a resolved_frame_index that must exactly match the semantic anchor indices derived from the plan (with -1 mapped to frame_count-1). This ValueError fires when any material's resolved index disagrees with the computed expectation tuple. It guards against plan/material desynchronization before canvas encoding begins.","triggerScenarios":"Calling minimax_h3_prepared_keyframes (directly or via _encode_fl2va_keyframes/_encode_target_keyframes) with keyframe materials whose resolved_frame_index values were built from a different plan (different frame_count or semantic_frame_indices), or materials mutated after plan resolution.","commonSituations":"Reusing cached keyframe materials across requests with different plans, partial regeneration of keyframes after changing frame_count or semantic anchors, or a bug upstream that reorders the keyframes list relative to semantic_indices.","solutions":["Rebuild the keyframe materials from the current plan so resolved_frame_index matches tuple(frame_count-1 if i==-1 else i for i in semantic_indices)","Verify the keyframes list order matches semantic_indices order before calling the stage","Discard any stale per-request caches of keyframe materials when the plan shape or anchors change"],"exampleFix":"// before\nkeyframes = cached_keyframes  # from an older plan\nresult = minimax_h3_prepared_keyframes(plan, keyframes, batch)\n// after\nkeyframes = build_keyframes_for_plan(plan)  # resolved_frame_index derived from current plan\nresult = minimax_h3_prepared_keyframes(plan, keyframes, batch)","handlingStrategy":"validation","validationCode":"expected = tuple(plan.frame_count - 1 if i == -1 else i for i in semantic_indices)\nresolved = tuple(m.resolved_frame_index for m in keyframes)\nassert resolved == expected, f'mismatch: {resolved} != {expected}'","typeGuard":"def keyframes_match_plan(plan, keyframes, semantic_indices) -> bool:\n    expected = tuple(plan.frame_count - 1 if i == -1 else i for i in semantic_indices)\n    return tuple(m.resolved_frame_index for m in keyframes) == expected","tryCatchPattern":null,"preventionTips":["Regenerate keyframe materials whenever the plan changes","Never mix materials from one plan with another plan object","Add an assertion right after material construction"],"tags":["minimax-h3","keyframes","validation","pipeline"],"backgroundTag":"plan-state-mismatch","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}