GopeedLab/gopeed · error
no parts found for %s
Error message
no parts found for %s
What it means
Returned by findZipMultiParts (extract_zip.go:59-86) when ZIP multi-part extraction finds no existing files matching the expected <base>.%03d sequence starting at .001. The caller strips the numeric suffix from firstPartPath, rebuilds Archive.zip.001, Archive.zip.002... via os.Stat, and a NotExist result on the very first part yields zero parts. It signals that the derived first-part filename does not exist on disk at extraction time.
Source
Thrown at pkg/download/extract_zip.go:82
// Remove the .001 suffix to get the base
if idx := strings.LastIndex(baseName, "."); idx > 0 {
baseName = baseName[:idx] // "Archive.zip"
}
var parts []string
partNum := 1
for {
partPath := filepath.Join(dir, baseName+fmt.Sprintf(".%03d", partNum))
if _, err := os.Stat(partPath); os.IsNotExist(err) {
break
}
parts = append(parts, partPath)
partNum++
}
if len(parts) == 0 {
return nil, fmt.Errorf("no parts found for %s", firstPartPath)
}
return parts, nil
}
// multiPartFileReader provides io.ReaderAt over multiple files concatenated
type multiPartFileReader struct {
parts []string
files []*os.File
sizes []int64
offsets []int64 // cumulative offsets for each file
totalSize int64
}
func newMultiPartFileReader(parts []string) *multiPartFileReader {
return &multiPartFileReader{parts: parts}
}
View on GitHub (pinned to 7b7327ffb3)
Solutions
- Verify the .001 first volume exists next to the parts you selected before triggering extraction
- Re-download or restore the missing first part so the full Archive.zip.001..NNN set is present in one directory
- Ensure part files keep the exact 3-digit suffix naming produced by the archiver
- If embedding, os.Stat the derived first part before calling extraction and surface a clearer error
Example fix
// before
err := extractMultiPartArchive("/data/Archive.zip.001", dest, "", nil)
// fails: /data/Archive.zip.001 was deleted after detection
// after
if _, err := os.Stat("/data/Archive.zip.001"); err != nil {
return fmt.Errorf("multi-part zip incomplete, first part missing: %w", err)
}
err := extractMultiPartArchive("/data/Archive.zip.001", dest, "", nil) Defensive patterns
Strategy: validation
Validate before calling
base := strings.TrimSuffix(firstPart, filepath.Ext(firstPart))
if _, err := os.Stat(base + ".001"); err != nil {
return fmt.Errorf("multi-part zip incomplete: %s.001 not found", base)
} Try / catch
if err := extractMultiPartArchive(p, dest, pw, cb); err != nil {
if strings.Contains(err.Error(), "no parts found for") {
log.Warn("first volume missing; re-download the .001 part")
}
return err
} Prevention
- Keep all volumes of a split archive in one directory with unmodified names
- Do not delete the .001 volume after downloading; extraction needs it
- Preserve the exact 3-digit .001/.002 naming produced by the archiver
- For embedders, stat the derived first part before starting extraction
When it happens
Trigger: The .001 part was deleted, moved or renamed after the archive was detected (auto-extract racing a user or cleanup job); the file set uses non-3-digit numbering (Archive.zip.1) that the %03d reconstruction never matches; the first part genuinely never downloaded; firstPartPath points into a directory that changed (relative path with a different process CWD).
Common situations: Post-download auto-extraction where a partial download only produced later-numbered parts; users manually deleting the first volume to save space; files renamed by browser dedupe (Archive (1).zip.001 breaking the base); NAS/docker deployments where the download directory is remapped between detection and extraction.
Related errors
AI-assisted analysis of GopeedLab/gopeed@7b7327ffb3 (2026-08-16).
Data as JSON: /api/errors/e19f813b5a96192e.
Report an issue: GitHub.