flipped-aurora/gin-vue-admin · error
保存技能包失败: %w
Error message
保存技能包失败: %w
What it means
This error wraps a failure to persist the downloaded online skill package (zip) to a temporary file on disk during DownloadOnlineSkill. The io.Copy call streams the HTTP response body into tmpFile; any read error from the network stream or write error to the local filesystem is wrapped with this message. It is a disk/IO failure, not a validation failure.
Source
Thrown at server/service/system/sys_skills.go:456
if err != nil {
return fmt.Errorf("下载压缩包失败: %w", err)
}
defer zipResp.Body.Close()
if zipResp.StatusCode != http.StatusOK {
return fmt.Errorf("下载压缩包失败, HTTP状态码: %d", zipResp.StatusCode)
}
tmpFile, err := os.CreateTemp("", "gva-skill-*.zip")
if err != nil {
return fmt.Errorf("创建临时文件失败: %w", err)
}
tmpPath := tmpFile.Name()
defer os.Remove(tmpPath)
if _, err = io.Copy(tmpFile, zipResp.Body); err != nil {
tmpFile.Close()
return fmt.Errorf("保存技能包失败: %w", err)
}
tmpFile.Close()
if err = extractZipToDir(tmpPath, skillsDir); err != nil {
return fmt.Errorf("解压技能包失败: %w", err)
}
return nil
}
func extractZipToDir(zipPath, destDir string) error {
r, err := zip.OpenReader(zipPath)
if err != nil {
return err
}
defer r.Close()
for _, f := range r.File {View on GitHub (pinned to 3136500ef3)
Solutions
- Check free disk space on the partition backing os.TempDir (or TMPDIR) and clean up if full
- Verify network connectivity/proxy stability to the skill download host and retry the download
- Ensure the process has write permission to the temp directory in your deployment environment
- Inspect the wrapped cause (%w) in logs to distinguish network read errors from file write errors
Example fix
// before
if _, err = io.Copy(tmpFile, zipResp.Body); err != nil {
tmpFile.Close()
return fmt.Errorf("保存技能包失败: %w", err)
}
// after
if _, err = io.Copy(tmpFile, zipResp.Body); err != nil {
tmpFile.Close()
if netErr, ok := err.(net.Error); ok {
return fmt.Errorf("下载网络中断,请重试: %w", netErr)
}
return fmt.Errorf("保存技能包失败: %w", err)
} Defensive patterns
Strategy: try-catch
Validate before calling
// Go: preflight checks before download
if st, err := os.Stat(os.TempDir()); err != nil || !st.IsDir() {
return fmt.Errorf("临时目录不可用")
}
if avail := diskFree(os.TempDir()); avail < minNeededBytes {
return fmt.Errorf("临时目录空间不足")
} Type guard
// Go: classify the wrapped error
func isNetErr(err error) bool {
var ne net.Error
return errors.As(err, &ne)
}
func isPathErr(err error) bool {
var pe *fs.PathError
return errors.As(err, &pe)
} Try / catch
err := svc.DownloadOnlineSkill(name)
if err != nil {
var pathErr *fs.PathError
if errors.As(err, &pathErr) && os.IsPermission(pathErr) {
// fix temp-dir permissions and retry
} else if errors.Is(err, syscall.ENOSPC) {
// free disk space and retry
}
log.Errorf("下载技能包失败: %v", err)
} Prevention
- Monitor temp-dir disk usage and alert before full
- Set TMPDIR to a writable volume in containers
- Retry downloads with backoff on transient network errors
- Log the unwrapped cause so network vs. disk errors are distinguishable
When it happens
Trigger: Calling DownloadOnlineSkill when the HTTP response body of the skill package download cannot be fully read (connection dropped mid-transfer) or when writing to the temp file fails (disk full, permission denied on os.TempDir, tmpFile already closed).
Common situations: Unstable network/proxy interrupting the download of the skill zip; insufficient disk space in the temp directory; restricted tmp permissions in containerized deployments; read-only filesystem after a disk remount.
Related errors
AI-assisted analysis of flipped-aurora/gin-vue-admin@3136500ef3 (2026-08-31).
Data as JSON: /api/errors/764b6ce9fcabb83e.
Report an issue: GitHub.