flipped-aurora/gin-vue-admin · error

解压技能包失败: %w

Error message

解压技能包失败: %w

What it means

This error wraps a failure from extractZipToDir when unzipping a downloaded skill package into the skills directory. It occurs after the zip was successfully saved to a temp file, so the cause is either a corrupt/invalid zip archive or filesystem errors creating/writing files under skillsDir. The wrapped %w error carries the underlying reason.

Source

Thrown at server/service/system/sys_skills.go:461

	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 {
		name := filepath.FromSlash(f.Name)
		if strings.Contains(name, "..") {
			continue
		}

View on GitHub (pinned to 3136500ef3)

Solutions

  1. Re-download the skill package and confirm the URL serves a valid zip (check HTTP status and Content-Type before extraction)
  2. Check permissions/ownership of the skills target directory and free disk space
  3. Validate the temp file is a zip (e.g. zip.OpenReader) before extracting to give a clearer message
  4. Inspect the wrapped cause in logs to see whether it is archive corruption or filesystem failure

Example fix

// before
zipResp := download(url)
io.Copy(tmpFile, zipResp.Body)
extractZipToDir(tmpPath, skillsDir)
// after
if zipResp.StatusCode != http.StatusOK {
    return fmt.Errorf("下载失败,状态码: %d", zipResp.StatusCode)
}
if _, err := zip.OpenReader(tmpPath); err != nil {
    return fmt.Errorf("下载内容不是有效 zip 包: %w", err)
}
extractZipToDir(tmpPath, skillsDir)
Defensive patterns

Strategy: validation

Validate before calling

// Go: verify it is a valid zip before extracting
if _, err := zip.OpenReader(tmpPath); err != nil {
    return fmt.Errorf("下载的文件不是有效的 zip 包: %w", err)
}
if st, err := os.Stat(destDir); err != nil || !st.IsDir() {
    return fmt.Errorf("目标目录不可写")
}

Type guard

// Go: check archive validity
func isZipFile(path string) bool {
    r, err := zip.OpenReader(path)
    if err != nil {
        return false
    }
    defer r.Close()
    return true
}

Try / catch

err := svc.DownloadOnlineSkill(name)
if err != nil {
    var zerr *zip.Error
    if errors.As(err, &zerr) {
        // corrupt archive: re-download the package
    }
    log.Errorf("解压技能包失败: %v", err)
}

Prevention

When it happens

Trigger: Calling DownloadOnlineSkill when extractZipToDir(tmpPath, skillsDir) fails: the downloaded file is not a valid zip (truncated download, HTML error page saved as zip), zip-slip or entry-extraction errors, or write/permission errors creating the target skill directory.

Common situations: Remote server returning a 4xx/5xx HTML page that gets saved and then fails unzip; interrupted download producing a truncated archive; skillsDir owned by another user or read-only volume; zip entries with illegal paths rejected by the extractor.

Related errors


AI-assisted analysis of flipped-aurora/gin-vue-admin@3136500ef3 (2026-08-31). Data as JSON: /api/errors/f85b6bc23e28fa77. Report an issue: GitHub.