{"record":{"id":"b83c7771c03c9f99","repo":"sgl-project/sglang","slug":"kimi-k3-cannot-mix-local-preprocessed-and-deferred","errorCode":null,"errorMessage":"Kimi-K3 cannot mix local preprocessed and deferred images","messagePattern":"Kimi-K3 cannot mix local preprocessed and deferred images","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/srt/models/kimi_k3.py","lineNumber":3405,"sourceCode":"            if device.type == \"cuda\" and device_index is None:\n                device_index = torch.cuda.current_device()\n\n            selected_items = []\n            for image_index in image_indices:\n                item = items[image_index]\n                if device.type == \"cuda\":\n                    item.reconstruct(\n                        device_index, ipc_consumer_count=ipc_consumer_count\n                    )\n                selected_items.append(item)\n\n            locally_preprocessed = [\n                item.model_specific_data.get(LOCAL_PREPROCESSED_KEY, False)\n                for item in selected_items\n            ]\n            if any(locally_preprocessed):\n                if not all(locally_preprocessed):\n                    raise ValueError(\n                        \"Kimi-K3 cannot mix local preprocessed and deferred images\"\n                    )\n                return materialize_multimodal_features(\n                    [item.feature for item in selected_items],\n                    device=device,\n                    dtype=target_dtype,\n                )\n\n            deferred = [\n                item.model_specific_data.get(DEFERRED_PREPROCESSING_KEY)\n                for item in selected_items\n            ]\n            if any(config is not None for config in deferred):\n                materialized = [None] * len(selected_items)\n                deferred_by_backend = {}\n                for index, (item, config) in enumerate(zip(selected_items, deferred)):\n                    if config is None:\n                        if not isinstance(item.feature, torch.Tensor):","sourceCodeStart":3387,"sourceCodeEnd":3423,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/srt/models/kimi_k3.py#L3387-L3423","documentation":"materialize_item_features() refuses batches that mix locally preprocessed images (LOCAL_PREPROCESSED_KEY=True) with deferred ones, raising ValueError. Mixing would require handling two incompatible feature paths in one batch, so the model requires all-or-nothing.","triggerScenarios":"A single get_image_feature() call where some selected items have model_specific_data[LOCAL_PREPROCESSED_KEY]=True and others don't.","commonSituations":"Multi-image requests where one image was preprocessed locally (e.g. CPU path) and others arrived via deferred GPU preprocessing; inconsistent flags set by different branches of the input pipeline.","solutions":["Group items by preprocessed-vs-deferred and call materialization per homogeneous group","Make the input pipeline set LOCAL_PREPROCESSED_KEY consistently for all items in a request","If using the deferred path, ensure all images in the batch carry deferred configs"],"exampleFix":"// before\nfeats = model.get_image_feature(mixed_items)\n\n// after\nlocal = [i for i in items if i.model_specific_data.get(LOCAL_PREPROCESSED_KEY)]\ndeferred = [i for i in items if not i.model_specific_data.get(LOCAL_PREPROCESSED_KEY)]\nfeats = model.get_image_feature(local) + model.get_image_feature(deferred)","handlingStrategy":"validation","validationCode":"flags = [i.model_specific_data.get(LOCAL_PREPROCESSED_KEY, False) for i in items]\nassert all(f == flags[0] for f in flags), \"do not mix local and deferred items\"","typeGuard":"def homogeneous_batch(items) -> bool:\n    flags = {bool(i.model_specific_data.get(LOCAL_PREPROCESSED_KEY, False)) for i in items}\n    return len(flags) == 1","tryCatchPattern":"try:\n    model.get_image_feature(items)\nexcept ValueError as e:\n    if \"mix\" in str(e):\n        groups = group_by_preprocessed_flag(items)\n        return [model.get_image_feature(g) for g in groups]\n    raise","preventionTips":["Set LOCAL_PREPROCESSED_KEY uniformly per request in the input pipeline","Batch only images that went through the same preprocessing path"],"tags":["kimi-k3","multimodal","preprocessing-mismatch"],"backgroundTag":"mixed-preprocessing-batch","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}