{"record":{"id":"a09efba919d18415","repo":"kopia/kopia","slug":"error-writing-pending-content","errorCode":null,"errorMessage":"error writing pending content","messagePattern":"error writing pending content","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"repo/content/content_manager.go","lineNumber":654,"sourceCode":"\tfp := append([]*pendingPackInfo(nil), bm.failedPacks...)\n\tfor _, pp := range fp {\n\t\tcontentlog.Log1(ctx, bm.log, \"retry-write\", blobparam.BlobID(\"packBlobID\", pp.packBlobID))\n\n\t\tif err := bm.writePackAndAddToIndexLocked(ctx, pp); err != nil {\n\t\t\treturn errors.Wrap(err, \"error writing previously failed pack\")\n\t\t}\n\t}\n\n\tfor len(bm.writingPacks) > 0 {\n\t\tcontentlog.Log1(ctx, bm.log, \"waiting for in-progress packs to finish\", logparam.Int(\"len\", len(bm.writingPacks)))\n\n\t\t// wait packs that are currently writing in other goroutines to finish\n\t\tbm.cond.Wait()\n\t}\n\n\t// finish all new pending packs\n\tif err := bm.finishAllPacksLocked(ctx); err != nil {\n\t\treturn errors.Wrap(err, \"error writing pending content\")\n\t}\n\n\tif err := bm.flushPackIndexesLocked(ctx, mp); err != nil {\n\t\treturn errors.Wrap(err, \"error flushing indexes\")\n\t}\n\n\treturn nil\n}\n\n// RewriteContent causes reads and re-writes a given content using the most recent format.\n// TODO(jkowalski): this will currently always re-encrypt and re-compress data, perhaps consider a\n// pass-through mode that preserves encrypted/compressed bits.\nfunc (bm *WriteManager) RewriteContent(ctx context.Context, contentID ID) error {\n\tcontentlog.Log1(ctx, bm.log, \"rewrite-content\",\n\t\tcontentparam.ContentID(\"contentID\", contentID))\n\n\tmp, mperr := bm.format.GetMutableParameters(ctx)\n\tif mperr != nil {","sourceCodeStart":636,"sourceCodeEnd":672,"githubUrl":"https://github.com/kopia/kopia/blob/82495e54b584c1ef6073c9e1be048f57f8aef078/repo/content/content_manager.go#L636-L672","documentation":"After waiting for in-flight packs, Flush calls finishAllPacksLocked to write all newly pending packs; this wrapper reports a failure there. It is essentially the same failure mode as 'error writing pack content' but raised from Flush's own finish step.","triggerScenarios":"Flush() → (after waiting for writingPacks) → finishAllPacksLocked → writePackAndAddToIndexLocked fails for a pending pack: pack preparation, blob upload, or mutable-parameter errors.","commonSituations":"Storage errors occurring exactly at flush time (quota hit, network drop); invalid format parameters configured since the last flush; cancellation of ctx while many packs flush at once during Close().","solutions":["Unwrap the inner cause to identify preparation vs upload failure.","Retry Flush after restoring storage access — pending packs are preserved until written.","Review recent changes to format parameters (compression, index version).","Avoid canceling the context mid-Flush; use WithoutCancel for shutdown flushes."],"exampleFix":"// before: canceling flush on shutdown signal\nctx, cancel := context.WithCancel(...)\ngo func() { <-sig; cancel() }()\nerr := bm.Flush(ctx)\n// after: keep flush alive through shutdown\nerr := bm.Flush(context.WithoutCancel(ctx))\nif err != nil { log.Printf(\"deferred flush needed: %v\", err) }","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Go: don't abort Close on transient flush failure; retry once\nif err := bm.Flush(ctx); err != nil {\n    err = bm.Flush(context.WithoutCancel(ctx))\n}","preventionTips":["Flush with WithoutCancel during shutdown","Keep format parameters stable between write sessions","Pre-flush large batches in chunks to reduce blast radius of a storage error"],"tags":["flush","pack","storage"],"backgroundTag":"file-write-failed","analyzedSha":"82495e54b584c1ef6073c9e1be048f57f8aef078","analyzedAt":"2026-09-07T20:35:21.689Z","contentChangedAt":"2026-09-07T20:35:21.689Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}