What happened / 发生了什么
对于带版本号命名的 skill(如 skill-writing-1.0.0),在 Skills 管理页面点击下载按钮后始终提示「下载失败」。对于不带版本号(不含 .)的普通 skill 名称(如 my-skill),下载正常。
Reproduce / 如何复现?
- 进入 配置 → Skills 页面
- 在本地 Skills 列表中,找到一个带版本号命名的 skill(如
skill-writing-1.0.0,版本号中包含 .)
- 点击该 skill 的下载按钮
- 观察:前端弹出错误提示「下载失败」,服务端日志中无任何报错信息
AstrBot version, deployment method (e.g., Windows Docker Desktop deployment), provider used, and messaging platform used. / AstrBot 版本、部署方式(如 Windows Docker Desktop 部署)、使用的提供商、使用的消息平台适配器
4.26.5 Windows Desktop
OS
Windows
Logs / 报错日志

让我们仔细观察,浏览器链接填的可是1.0.0,但是下面返回错误信息却变成了1.0,名称都变了自然是找不到。
这个报错信息不是默认有的,我是改了App里面直接捕捉未处理的错误信息才能让这个得到显示,也就是完成
#9269 的修复。
不同命名模式的对比
| skill 名称 |
下载结果 |
my-skill |
✅ 正常下载 |
my.cool.skill |
❌ 下载失败 |
skill-writing-1.0.0 |
❌ 下载失败 |
pdf-0.1.0 |
❌ 下载失败 |
根因
services/skills_service.py 第 446 行:
zip_base = export_dir / skill_name
zip_path = zip_base.with_suffix(".zip")
Path.with_suffix() 只替换最后一个后缀。问题在于:
shutil.make_archive(str(zip_base), "zip", ...) 将 ".zip" 追加到完整名称,产生 .../skill-writing-1.0.0.zip
- 但
Path(".../skill-writing-1.0.0").with_suffix(".zip") 把 .0 视为后缀并替换,得到 .../skill-writing-1.0.zip
- 两个文件名不匹配,后续
FileResponse 因找不到文件而抛出 RuntimeError,但该异常在前端只显示为「下载失败」
具体流程:
zip_base = Path(".../skill_exports/skill-writing-1.0.0")
→ zip_base.with_suffix(".zip") → ".../skill-writing-1.0.zip" ← Path 认为 ".0" 是 suffix
→ shutil.make_archive(str(zip_base), "zip", ...) → 创建 ".../skill-writing-1.0.0.zip"
→ FileResponse(zip_path= ".../skill-writing-1.0.zip") → 文件不存在 → RuntimeError
对于不含 . 的名称,.with_suffix(".zip") 表现正常(只有一个 suffix),所以 bug 仅影响带版本号的 skill。
触发条件
| 条件 |
说明 |
| skill 名称 |
包含 .(至少两个部分,即 stem 和 suffix 在 Path 语义下不同) |
| 操作 |
点击下载按钮触发 download_skill() |
影响范围
修复建议
将 zip_base.with_suffix(".zip") 替换为 Path(str(zip_base) + ".zip"),与 shutil.make_archive 的文件命名保持一致:
zip_path = Path(str(zip_base) + ".zip")
Are you willing to submit a PR? / 你愿意提交 PR 吗?
Code of Conduct
What happened / 发生了什么
对于带版本号命名的 skill(如
skill-writing-1.0.0),在 Skills 管理页面点击下载按钮后始终提示「下载失败」。对于不带版本号(不含.)的普通 skill 名称(如my-skill),下载正常。Reproduce / 如何复现?
skill-writing-1.0.0,版本号中包含.)AstrBot version, deployment method (e.g., Windows Docker Desktop deployment), provider used, and messaging platform used. / AstrBot 版本、部署方式(如 Windows Docker Desktop 部署)、使用的提供商、使用的消息平台适配器
4.26.5 Windows Desktop
OS
Windows
Logs / 报错日志
不同命名模式的对比
my-skillmy.cool.skillskill-writing-1.0.0pdf-0.1.0根因
services/skills_service.py第 446 行:Path.with_suffix()只替换最后一个后缀。问题在于:shutil.make_archive(str(zip_base), "zip", ...)将".zip"追加到完整名称,产生.../skill-writing-1.0.0.zipPath(".../skill-writing-1.0.0").with_suffix(".zip")把.0视为后缀并替换,得到.../skill-writing-1.0.zipFileResponse因找不到文件而抛出RuntimeError,但该异常在前端只显示为「下载失败」具体流程:
对于不含
.的名称,.with_suffix(".zip")表现正常(只有一个 suffix),所以 bug 仅影响带版本号的 skill。触发条件
.(至少两个部分,即stem和suffix在 Path 语义下不同)download_skill()影响范围
修复建议
将
zip_base.with_suffix(".zip")替换为Path(str(zip_base) + ".zip"),与shutil.make_archive的文件命名保持一致:Are you willing to submit a PR? / 你愿意提交 PR 吗?
Code of Conduct