{"record":{"id":"9e84681cc45f9a0e","repo":"restic/restic","slug":"download-error-w","errorCode":null,"errorMessage":"download error: %w","messagePattern":"download error: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/repository/checker.go","lineNumber":467,"sourceCode":"\t\t\treturn &partialReadError{err}\n\t\t}\n\n\t\thash = restic.IDFromHash(hrd.Sum(nil))\n\t\treturn nil\n\t})\n\terrs = append(errs, blobErrors...)\n\tif err != nil {\n\t\tvar e *partialReadError\n\t\tisPartialReadError := errors.As(err, &e)\n\t\t// failed to load the pack file, return as further checks cannot succeed anyways\n\t\tdebug.Log(\"  error streaming pack (partial %v): %v\", isPartialReadError, err)\n\t\tif isPartialReadError {\n\t\t\treturn &ErrPackData{PackID: id, errs: append(errs, fmt.Errorf(\"partial download error: %w\", err))}\n\t\t}\n\n\t\t// The check command suggests to repair files for which a `ErrPackData` is returned. However, this file\n\t\t// completely failed to download such that there's no point in repairing anything.\n\t\treturn fmt.Errorf(\"download error: %w\", err)\n\t}\n\tif !hash.Equal(id) {\n\t\tdebug.Log(\"pack ID does not match, want %v, got %v\", id, hash)\n\t\treturn &ErrPackData{PackID: id, errs: append(errs, errors.Errorf(\"unexpected pack id %v\", hash))}\n\t}\n\n\tblobs, hdrSize, err := pack.List(r.Key(), bytes.NewReader(hdrBuf), int64(len(hdrBuf)))\n\tif err != nil {\n\t\treturn &ErrPackData{PackID: id, errs: append(errs, err)}\n\t}\n\n\tif uint32(idxHdrSize) != hdrSize {\n\t\tdebug.Log(\"Pack header size does not match, want %v, got %v\", idxHdrSize, hdrSize)\n\t\terrs = append(errs, errors.Errorf(\"pack header size does not match, want %v, got %v\", idxHdrSize, hdrSize))\n\t}\n\n\tfor _, blob := range blobs {\n\t\t// Check if blob is contained in index and position is correct","sourceCodeStart":449,"sourceCodeEnd":485,"githubUrl":"https://github.com/restic/restic/blob/a80be1478a4c537f8396e0db2b05120aa78f11e0/internal/repository/checker.go#L449-L485","documentation":"The same pack streaming path as the partial case, but here the pack could not be downloaded at all. restic deliberately returns a plain wrapped download error rather than ErrPackData, because the check command's repair suggestions are pointless when no data could be read.","triggerScenarios":"Backend unreachable or authentication rejected mid-run; the pack object deleted or unreadable; DNS or TLS failures; a repository being concurrently reorganized, for example by an interrupted prune.","commonSituations":"Expired tokens during long checks; object-storage outages; objects removed by another process; wrong permissions on specific prefixes.","solutions":["Verify the backend is reachable and credentials are valid (restic list keys is a cheap probe)","Re-run the check once transport is healthy","If the object is permanently gone, restore the repository from another copy or re-backup the source data","Check whether a crashed concurrent prune left the repository half-modified, then run restic check"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// cheap reachability probe before a long check run\nif _, err := repo.List(ctx, restic.KeyFile); err != nil {\n    return fmt.Errorf(\"backend not ready, aborting check: %w\", err)\n}","typeGuard":"func isDownloadError(err error) bool {\n    var pd *repository.ErrPackData\n    return err != nil && !errors.As(err, &pd) && strings.Contains(err.Error(), \"download error\")\n}","tryCatchPattern":"err := checkPack(ctx, r, id, blobs, size, bufRd, dec)\nif err != nil {\n    var pd *repository.ErrPackData\n    if errors.As(err, &pd) {\n        reportCorruption(pd.PackID) // partial data: repair path\n    } else {\n        return retryLater(err) // full download failure: retry once backend is healthy\n    }\n}","preventionTips":["Verify credentials and connectivity before starting long check runs","Avoid running prune and check concurrently on the same repository","Use exponential backoff around backend outages instead of tight retries","Keep an offsite copy so permanently unreadable objects are recoverable"],"tags":["check","download","backend","connectivity"],"backgroundTag":null,"analyzedSha":"a80be1478a4c537f8396e0db2b05120aa78f11e0","analyzedAt":"2026-08-15T15:30:29.928Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}