{"record":{"id":"3da19e4d5d2cc414","repo":"sgl-project/sglang","slug":"qwenimage-rope-text-cache-overflow-before-denoisin","errorCode":null,"errorMessage":"QwenImage RoPE text cache overflow before denoising: required_txt_seq_len={max_txt_seq_len}, txt_cache_len={txt_cache_len}, overflow={overflow}. Please reduce the number of input images, shorten the prompt, or lower the requested resolution.","messagePattern":"QwenImage RoPE text cache overflow before denoising: required_txt_seq_len=(.+?), txt_cache_len=(.+?), overflow=(.+?)\\. Please reduce the number of input images, shorten the prompt, or lower the requested resolution\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/multimodal_gen/configs/pipeline_configs/qwen_image.py","lineNumber":307,"sourceCode":"            vae_arch_config.latents_std, device=device\n        ).view(1, vae_arch_config.z_dim, 1, 1, 1).to(device, dtype)\n        shift_factor = (\n            torch.tensor(vae_arch_config.latents_mean)\n            .view(1, vae_arch_config.z_dim, 1, 1, 1)\n            .to(device, dtype)\n        )\n        return scaling_factor, shift_factor\n\n    @staticmethod\n    def get_freqs_cis(img_shapes, txt_seq_lens, rotary_emb, device, dtype):\n        # img_shapes: for global entire image\n        img_freqs, txt_freqs = rotary_emb(img_shapes, txt_seq_lens, device=device)\n\n        max_txt_seq_len = max(txt_seq_lens) if txt_seq_lens else 0\n        txt_cache_len = int(txt_freqs.shape[0])\n        if max_txt_seq_len > txt_cache_len:\n            overflow = max_txt_seq_len - txt_cache_len\n            raise ValueError(\n                \"QwenImage RoPE text cache overflow before denoising: \"\n                f\"required_txt_seq_len={max_txt_seq_len}, txt_cache_len={txt_cache_len}, \"\n                f\"overflow={overflow}. \"\n                \"Please reduce the number of input images, shorten the prompt, \"\n                \"or lower the requested resolution.\"\n            )\n\n        # flashinfer RoPE expects a float32 cos/sin cache concatenated on the last dim\n        img_cos_half = img_freqs.real.to(dtype=torch.float32).contiguous()\n        img_sin_half = img_freqs.imag.to(dtype=torch.float32).contiguous()\n        txt_cos_half = txt_freqs.real.to(dtype=torch.float32).contiguous()\n        txt_sin_half = txt_freqs.imag.to(dtype=torch.float32).contiguous()\n\n        img_cos_sin_cache = torch.cat([img_cos_half, img_sin_half], dim=-1)\n        txt_cos_sin_cache = torch.cat([txt_cos_half, txt_sin_half], dim=-1)\n        return img_cos_sin_cache, txt_cos_sin_cache\n\n    def _prepare_cond_kwargs(","sourceCodeStart":289,"sourceCodeEnd":325,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/multimodal_gen/configs/pipeline_configs/qwen_image.py#L289-L325","documentation":"QwenImage precomputes RoPE frequency tables (freqs_cis) sized for a text cache based on the resolved sequence lengths. If the actual maximum text sequence length exceeds the cached txt_freqs rows (e.g. because embeddings/conditioning expanded the text length beyond what the rotary embedding cache was allocated for), generation aborts before denoising starts.","triggerScenarios":"Very long prompts combined with multiple input images in QwenImage/QwenImageEditPlus; requesting high resolution (which reallocates caches for image tokens and squeezes the text cache); reusing a freqs_cis cache created for a shorter prompt batch on a longer one.","commonSituations":"Sending a long detailed editing instruction; many condition images increasing reserved sequence budget; the rotary-emb cache sized from a stale/shorter shape after a previous smaller request in the same session.","solutions":["Shorten the prompt text and retry","Reduce the number of input condition images","Lower the requested output resolution","Recompute/invalidate the RoPE cache so it is rebuilt for the current sequence lengths before get_freqs_cis is called"],"exampleFix":"// before\nprompt = \"<2000-token detailed editing instruction>\"\nimages = [img1, img2, img3, img4]\n\n// after\nprompt = \"Make the sky sunset-colored and add reflections\"  # shorter\nimages = [img1]  # fewer condition images","handlingStrategy":"validation","validationCode":"# Estimate text length before generation\nest_tokens = len(tokenizer(prompt).input_ids)\nassert est_tokens < txt_cache_budget, (\n    f\"prompt ~{est_tokens} tokens exceeds text cache budget {txt_cache_budget}\")","typeGuard":null,"tryCatchPattern":"try:\n    freqs = pipe.get_freqs_cis(img_shapes, txt_seq_lens)\nexcept ValueError as e:\n    if \"text cache overflow\" in str(e):\n        prompt = summarize(prompt)  # shorten and retry once\n        freqs = pipe.get_freqs_cis(img_shapes, [len(tokenizer(prompt).input_ids)])\n    else:\n        raise","preventionTips":["Cap prompt length client-side (e.g. 512 tokens) for image editing","Limit condition image count per request","Avoid reusing RoPE caches across requests with different prompt lengths"],"tags":["qwen-image","rope","sequence-length","cache-overflow","multimodal"],"backgroundTag":"kv-cache-capacity-exceeded","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}