Problem
The skill archive download endpoints return a ZIP file on success, but failed archive preparation currently returns a JSON error envelope with HTTP 200.
Affected endpoints:
GET /api/v1/skills/archive?skill_name=...
GET /api/v1/skills/{skill_name}/archive
- legacy
GET /api/skills/download?name=...
This is confusing for callers that treat these endpoints as binary downloads. The dashboard calls the v1 query endpoint with responseType: 'blob', wraps the response as application/zip, and saves it as <skill>.zip. If the backend returns a 200 JSON error body, the browser can save an error payload as a fake ZIP archive.
Reproduction sketch
- Request a skill archive for a local skill that cannot be exported, such as a missing skill or a plugin-provided/sandbox-only skill.
- Backend
SkillsService.prepare_skill_archive() raises SkillsServiceError.
_download_skill() catches the exception and returns error(str(exc)).
- FastAPI serializes that dict as HTTP 200 JSON.
- Blob/ZIP callers treat the response as a successful archive download.
Expected behavior
Failed skill archive downloads should return a non-2xx HTTP error while preserving the existing JSON error shape.
Actual behavior
Failed skill archive downloads can return HTTP 200 with a JSON error body.
Problem
The skill archive download endpoints return a ZIP file on success, but failed archive preparation currently returns a JSON error envelope with HTTP 200.
Affected endpoints:
GET /api/v1/skills/archive?skill_name=...GET /api/v1/skills/{skill_name}/archiveGET /api/skills/download?name=...This is confusing for callers that treat these endpoints as binary downloads. The dashboard calls the v1 query endpoint with
responseType: 'blob', wraps the response asapplication/zip, and saves it as<skill>.zip. If the backend returns a 200 JSON error body, the browser can save an error payload as a fake ZIP archive.Reproduction sketch
SkillsService.prepare_skill_archive()raisesSkillsServiceError._download_skill()catches the exception and returnserror(str(exc)).Expected behavior
Failed skill archive downloads should return a non-2xx HTTP error while preserving the existing JSON error shape.
Actual behavior
Failed skill archive downloads can return HTTP 200 with a JSON error body.