cli/cli · error
error extracting %q: %w
Error message
error extracting %q: %w
What it means
ExtractZip iterates archive entries, resolves each entry name against destDir via safepaths (path-traversal entries are silently skipped), then calls extractZipFile. If opening the entry, creating the destination file (O_EXCL, so pre-existing files fail), MkdirAll, or io.Copy fails, the error is wrapped with the offending entry name. Note the O_EXCL flag: extracting into a dirty destination where a file already exists produces "file already exists".
Source
Thrown at internal/zip/zip.go:36
)
// ExtractZip extracts the contents of a zip archive to destDir.
// Files that would result in path traversal are silently skipped.
// Files that would produce any other error cause the extraction to be aborted,
// and the error is returned.
func ExtractZip(zr *zip.Reader, destDir safepaths.Absolute) error {
for _, zf := range zr.File {
fpath, err := destDir.Join(zf.Name)
if err != nil {
var pathTraversalError safepaths.PathTraversalError
if errors.As(err, &pathTraversalError) {
continue
}
return err
}
if err := extractZipFile(zf, fpath); err != nil {
return fmt.Errorf("error extracting %q: %w", zf.Name, err)
}
}
return nil
}
func extractZipFile(zf *zip.File, dest safepaths.Absolute) (extractErr error) {
zm := zf.Mode()
if zm.IsDir() {
extractErr = os.MkdirAll(dest.String(), dirMode)
return
}
var f io.ReadCloser
f, extractErr = zf.Open()
if extractErr != nil {
return
}
defer f.Close()View on GitHub (pinned to 0eeec0b92e)
Solutions
- Clean the destination directory before extracting (remove partial output), since O_EXCL fails on existing files
- Check free disk space and write permissions on destDir
- Verify the archive integrity (unzip -t archive.zip) and re-download if the transfer was truncated
- If embedding, call ExtractZip only into a fresh empty directory you created
Example fix
// before
os.MkdirAll(dest, 0o755)
err := zip.ExtractZip(zr, dest) // re-run -> error extracting "skill/README.md": ... file exists
// after
os.RemoveAll(dest)
if err := os.MkdirAll(dest, 0o755); err != nil { return err }
err := zip.ExtractZip(zr, dest) Defensive patterns
Strategy: validation
Validate before calling
// extract only into a fresh directory; O_EXCL makes re-extraction fail
if err := os.RemoveAll(dest); err != nil { return err }
if err := os.MkdirAll(dest, 0o755); err != nil { return err }
if err := zip.ExtractZip(zr, safepaths.MustNewAbsolute(dest)); err != nil { return err } Try / catch
err := zip.ExtractZip(zr, dest)
if err != nil {
var target safepaths.Absolute // best-effort cleanup so retry can succeed
_ = os.RemoveAll(dest.String())
return err
} Prevention
- Treat extraction as non-idempotent: always start from an empty destination
- Verify archives (entry count/CRC) after download and before extraction
- Check disk space and destination permissions before extracting
When it happens
Trigger: Extracting a zip whose target file already exists in destDir (re-run over a partially extracted directory); disk full or permission denied during copy; unreadable/corrupt zip entry data; parent directory creation blocked.
Common situations: Retrying a failed download-extract without cleaning the destination; extracting into a directory owned by another user; truncated archive downloads producing CRC/open errors mid-entry.
Related errors
- there are no enabled workflows to disable
- there are no disabled workflows to enable
- failed to close local tcp port listener: %w
- failed to read public key file: %w
- failed to migrate as %q pre migration version did not match
AI-assisted analysis of cli/cli@0eeec0b92e (2026-08-15).
Data as JSON: /api/errors/9bc11e0110dc04a4.
Report an issue: GitHub.