{"record":{"id":"e19f813b5a96192e","repo":"GopeedLab/gopeed","slug":"no-parts-found-for-s","errorCode":null,"errorMessage":"no parts found for %s","messagePattern":"no parts found for (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/download/extract_zip.go","lineNumber":82,"sourceCode":"\t// Remove the .001 suffix to get the base\n\tif idx := strings.LastIndex(baseName, \".\"); idx > 0 {\n\t\tbaseName = baseName[:idx] // \"Archive.zip\"\n\t}\n\n\tvar parts []string\n\tpartNum := 1\n\n\tfor {\n\t\tpartPath := filepath.Join(dir, baseName+fmt.Sprintf(\".%03d\", partNum))\n\t\tif _, err := os.Stat(partPath); os.IsNotExist(err) {\n\t\t\tbreak\n\t\t}\n\t\tparts = append(parts, partPath)\n\t\tpartNum++\n\t}\n\n\tif len(parts) == 0 {\n\t\treturn nil, fmt.Errorf(\"no parts found for %s\", firstPartPath)\n\t}\n\n\treturn parts, nil\n}\n\n// multiPartFileReader provides io.ReaderAt over multiple files concatenated\ntype multiPartFileReader struct {\n\tparts     []string\n\tfiles     []*os.File\n\tsizes     []int64\n\toffsets   []int64 // cumulative offsets for each file\n\ttotalSize int64\n}\n\nfunc newMultiPartFileReader(parts []string) *multiPartFileReader {\n\treturn &multiPartFileReader{parts: parts}\n}\n","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/GopeedLab/gopeed/blob/7b7327ffb30816273a74b142cccc0bc10c5a4c67/pkg/download/extract_zip.go#L64-L100","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before\nerr := extractMultiPartArchive(\"/data/Archive.zip.001\", dest, \"\", nil)\n// fails: /data/Archive.zip.001 was deleted after detection\n\n// after\nif _, err := os.Stat(\"/data/Archive.zip.001\"); err != nil {\n\treturn fmt.Errorf(\"multi-part zip incomplete, first part missing: %w\", err)\n}\nerr := extractMultiPartArchive(\"/data/Archive.zip.001\", dest, \"\", nil)","handlingStrategy":"validation","validationCode":"base := strings.TrimSuffix(firstPart, filepath.Ext(firstPart))\nif _, err := os.Stat(base + \".001\"); err != nil {\n\treturn fmt.Errorf(\"multi-part zip incomplete: %s.001 not found\", base)\n}","typeGuard":null,"tryCatchPattern":"if err := extractMultiPartArchive(p, dest, pw, cb); err != nil {\n\tif strings.Contains(err.Error(), \"no parts found for\") {\n\t\tlog.Warn(\"first volume missing; re-download the .001 part\")\n\t}\n\treturn err\n}","preventionTips":["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"],"tags":["zip","multi-part","extraction","archive","filesystem"],"backgroundTag":null,"analyzedSha":"7b7327ffb30816273a74b142cccc0bc10c5a4c67","analyzedAt":"2026-08-16T02:51:03.250Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}