RuntimeError: Already borrowed

该报错出现在 vLLM 服务化部署 Qwen3.5-122B-A10B-FP8 等大型 MoE 模型时,当大量并发请求(尤其是包含 image_url 内容的多模态请求)通过 /v1/chat/completions 接口发送,导致 EngineCore 进程崩溃。同一并发量下纯文本请求可以稳定运行

RuntimeError: Already borrowed

RuntimeError: Already borrowed

快速结论:“RuntimeError: Already borrowed” 通常在使用 HuggingFace fast tokenizer 处理高并发多模态请求时触发,原因是 Rust borrow checker 在 tokenizer 内部发生冲突。优先排查 transformerstokenizers 库的版本是否匹配 vLLM 依赖要求。

问题场景

该报错出现在 vLLM 服务化部署 Qwen3.5-122B-A10B-FP8 等大型 MoE 模型时,当大量并发请求(尤其是包含 image_url 内容的多模态请求)通过 /v1/chat/completions 接口发送,导致 EngineCore 进程崩溃。同一并发量下纯文本请求可以稳定运行。此外,该报错在 tool_choice: required 的 tool-heavy 对话场景下也被观察到,且不仅限于图像请求。

报错原文

RuntimeError: Already borrowed
  File "transformers/tokenization_utils_fast.py", line 494
    self._tokenizer.enable_truncation(**target)

同时伴随日志警告:

WARNING [context.py:276] Failed to acquire tokenizer in current thread.
Retrying (1/5)...

以及 EngineCore 崩溃日志:

ERROR [core_client.py] Engine core proc EngineCore_DP0 died unexpectedly,
                        shutting down client.
ERROR [async_llm.py]   AsyncLLM output_handler failed.
vllm.v1.engine.exceptions.EngineDeadError: EngineCore encountered an issue.

原因分析

根本原因在于 HuggingFace fast tokenizer 基于 Rust 实现的线程安全性缺陷。高并发多模态请求(以及 tool-heavy 对话)会导致多个请求线程几乎同时试图修改同一个 tokenizer 内部的 truncation 设置,触发 Rust borrow checker 检测到非法并发借用,抛出 “Already borrowed” 错误。

此错误对单个请求可恢复(有重试机制),但高负载下会累积并最终导致 EngineCore 进程不稳定而崩溃。虽然 Issue 标题描述为图像请求触发,但在 tool-heavy 纯文本场景下也能复现,表明这不是多模态独有的问题。

此外,用户尝试使用 NCCL 2.28.0-2.29.2 版本时,在 aarch64 平台上可能因 NCCL 的 proxy-op slot 泄露导致额外的 hang 问题(表现为 60 秒后出现 “No available shared memory broadcast block found” 日志),但这属于独立于 tokenizer 报错的不同问题。

环境排查

  • 确认 vLLM 版本(受影响版本 0.17.1,但在 0.19.0 也能复现;作者建议尝试 nightly wheel)。
  • 检查 transformerstokenizers 版本:
    pip show vllm transformers tokenizers
  • 确认 Python 版本(建议 3.10+)。
  • 确认 CUDA / PyTorch 版本及 GPU 配置(如 tensor_parallel_size、GPU 类型和显存)。
  • 如果使用 Grace-Blackwell / DGX Spark 等 aarch64 平台,检查 NCCL 版本(python -c "import torch; print(torch.cuda.nccl.version())")。

解决步骤

  1. 可优先尝试:升级 vLLM 到最新版本(如 0.19.0 或 nightly wheel)。 Issue 作者确认在 latest main branch 上无法复现此问题,建议用户尝试 nightly wheel,但另一用户反馈在 v0.18.0 和 v0.19.0 下依然出现。升级可能减少但不是保证消除问题。
  2. 检查 transformers 和 tokenizers 版本组合。 确保版本匹配 vLLM 的依赖要求(v0.19.0 要求 transformers >= 4.56, < 5),并尝试固定高版本(如 transformers 4.57.6 + tokenizers 0.22.2)。
  3. 如果报错同时伴随 “No available shared memory broadcast block found” 并且处于 aarch64 平台,优先升级 NCCL。 执行:
    pip install nvidia-nccl-cu13==2.29.7

    注意:需要 CUDA 13 或对应版本的 NCCL 包。其他 CUDA 版本请参考官方文档替换正确包名。

  4. 尝试降低并发量。 Issue 中有用户询问“降低并发是否能缓解”,这会给出肯定答复。如果问题仅出现于高并发场景,可减少 max_num_seqs 或限制并发请求数作为临时规避手段。
  5. 清理并 restart 服务。 发生 crash 后 EngineCore 进程需要完全重启才能恢复。
  6. 将问题扩展到 tool-heavy 场景。 如果 crash 也出现在工具调用(function calling)场景,确认 tool 的返回内容是否过大,尝试减少单次 tool 负载。

验证方法

启动服务后,发送 10 个或更多并发多模态请求(包含 image_url 或 tool_choice: required),持续运行数分钟。观察:

  • 服务日志不再出现 RuntimeError: Already borrowedFailed to acquire tokenizer 警告。
  • EngineCore 进程稳定运行,不出现 “died unexpectedly” 日志。
  • 所有请求正常返回,无 400/500 错误。

参考来源

vllm-project/vllm #37602

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

celebrityanime
celebrityanime
文章: 14823

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注