fix(preprocess): handle Windows path_mapping rules without crashing#8875
fix(preprocess): handle Windows path_mapping rules without crashing#8875he-yufeng wants to merge 1 commit into
Conversation
The preprocess stage split each path_mapping rule on a bare ":", which raises "too many values to unpack" for Windows drive-letter rules (e.g. "C:/a:D:/b") and "not enough values" for rules without a colon. Delegate to path_Mapping, which already handles Windows/Linux/malformed rules and is the helper the respond stage already uses.
There was a problem hiding this comment.
Code Review
This pull request refactors the path mapping logic in the preprocessing stage to use the path_Mapping utility, preventing crashes on Windows-style drive-letter rules, and adds a test case to verify this behavior. The reviewer pointed out a critical issue in the imported path_Mapping function: it uses os.path.exists to detect Windows paths, which fails in Docker or cross-platform environments where the remote path does not exist locally. A robust alternative checking for drive-letter patterns was suggested to resolve this limitation.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| # Delegate to path_Mapping so Windows drive-letter rules | ||
| # (e.g. "C:/a:D:/b") and malformed rules are handled instead | ||
| # of crashing on a bare ":" split, matching the respond stage. | ||
| component.url = path_Mapping(mappings, component.url) |
There was a problem hiding this comment.
⚠️ path_Mapping 存在严重逻辑缺陷,导致 Windows 路径映射在大多数情况下失效
虽然此 PR 成功避免了 preprocess_stage 崩溃,但直接复用的 path_Mapping(位于 astrbot/core/utils/path_util.py)内部存在一个严重的逻辑缺陷:
在 path_util.py 中,它使用 os.path.exists(rule[0] + ":" + rule[1]) 来判断规则是否为 Windows 路径。
- 如果是在 Linux/Docker 环境下运行,或者在 Windows 上但该远程路径(如
C:/remote)在本地并不实际存在,os.path.exists将返回False。 - 这会导致像
C:/remote:D:/local这样包含 4 个部分的规则落入else分支,被误判为“格式错误”并直接跳过(伴随一条警告日志)。
由于路径映射的初衷通常就是将本地不存在的远程路径映射为本地存在的路径,这一限制导致该功能在跨平台或容器化部署时几乎完全失效。
💡 建议修复方案
建议修改 astrbot/core/utils/path_util.py 中的 path_Mapping 函数,通过判断首个分段是否为单个英文字母(Windows 盘符)来识别 Windows 路径,而不是依赖 os.path.exists:
def path_Mapping(mappings, srcPath: str) -> str:
for mapping in mappings:
rule = mapping.split(":")
if len(rule) == 2:
from_, to_ = mapping.split(":")
elif len(rule) > 4 or len(rule) == 1:
logger.warning(f"路径映射规则错误: {mapping}")
continue
# 通过盘符特征(单字母且为字母)判断,不依赖本地文件是否存在
elif len(rule[0]) == 1 and rule[0].isalpha():
from_ = rule[0] + ":" + rule[1]
if len(rule) == 3:
to_ = rule[2]
else:
to_ = rule[2] + ":" + rule[3]
else:
from_ = rule[0]
if len(rule) == 3:
to_ = rule[1] + ":" + rule[2]
else:
logger.warning(f"路径映射规则错误: {mapping}")
continue
问题
PreProcessStage在做媒体路径映射时,对每条path_mapping规则用了from_, to_ = mapping.split(":")。这假设规则里恰好有一个冒号,但实际上:C:/remote:D:/local)会被切成 4 段 →ValueError: too many values to unpack (expected 2)badmapping)→ValueError: not enough values to unpack任何配置了
path_mapping的 Windows 部署,只要收到带图片/语音的消息,preprocess stage 就会在这一行崩掉,整个 pipeline 中断。修复
直接复用已有的
astrbot.core.utils.path_util.path_Mapping——它已经正确处理 Windows 盘符、Linux 路径和格式错误的规则(多余/缺失冒号时告警跳过而非抛异常),而且 respond stage 早就在用它。preprocess stage 改成调用同一个 helper,行为与之前的单冒号场景一致,同时不再崩溃。验证
python -m pytest tests/test_preprocess_stage.py新增
test_preprocess_path_mapping_tolerates_multi_colon_rules覆盖带盘符冒号的规则;回退本次改动时该用例(以及已有的test_preprocess_path_mapping_accepts_file_uri在 Windows 上)会以too many values to unpack失败,修复后全部通过。ruff check与ruff format --check均通过。Summary by Sourcery
Fix media URL path mapping in the preprocess stage to safely handle Windows-style and malformed path_mapping rules without crashing.
Bug Fixes:
Tests: