{"record":{"id":"e24b8927453bcc57","repo":"kopia/kopia","slug":"unable-to-prepare-content-preamble","errorCode":null,"errorMessage":"unable to prepare content preamble","messagePattern":"unable to prepare content preamble","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"repo/content/content_manager.go","lineNumber":775,"sourceCode":"\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"unable to get session ID\")\n\t}\n\n\tblobID := make([]byte, packBlobIDLength)\n\tif _, err := cryptorand.Read(blobID); err != nil {\n\t\treturn nil, errors.Wrap(err, \"unable to read crypto bytes\")\n\t}\n\n\tsuffix, berr := bm.format.RepositoryFormatBytes(ctx)\n\tif berr != nil {\n\t\treturn nil, errors.Wrap(berr, \"format bytes\")\n\t}\n\n\tb.Append(suffix)\n\n\t//nolint:gosec\n\tif err := writeRandomBytesToBuffer(b, rand.Intn(bm.maxPreambleLength-bm.minPreambleLength+1)+bm.minPreambleLength); err != nil {\n\t\treturn nil, errors.Wrap(err, \"unable to prepare content preamble\")\n\t}\n\n\tbm.pendingPacks[prefix] = &pendingPackInfo{\n\t\tprefix:           prefix,\n\t\tpackBlobID:       blob.ID(fmt.Sprintf(\"%v%x-%v\", prefix, blobID, sessionID)),\n\t\tcurrentPackItems: map[ID]Info{},\n\t\tcurrentPackData:  b,\n\t}\n\n\treturn bm.pendingPacks[prefix], nil\n}\n\n// SupportsContentCompression returns true if content manager supports content-compression.\nfunc (bm *WriteManager) SupportsContentCompression() bool {\n\tmp := bm.format.GetCachedMutableParameters()\n\n\treturn mp.IndexVersion >= index.Version2\n}","sourceCodeStart":757,"sourceCodeEnd":793,"githubUrl":"https://github.com/kopia/kopia/blob/82495e54b584c1ef6073c9e1be048f57f8aef078/repo/content/content_manager.go#L757-L793","documentation":"While building a new pending pack, the manager writes a random-length preamble of random bytes via writeRandomBytesToBuffer to make pack blob IDs/content harder to fingerprint. If that write fails the error is wrapped with 'unable to prepare content preamble'. The only failure mode is the underlying crypto/rand read failing inside writeRandomBytesToBuffer.","triggerScenarios":"Creating a new pending pack when the random byte generation fails — entropy source unavailable, fd exhaustion, or CSPRNG blocked by the sandbox.","commonSituations":"Same environment issues as crypto/rand failures: containers missing /dev/urandom, seccomp blocking getrandom, severe resource exhaustion.","solutions":["Verify /dev/urandom availability and getrandom(2) support in the runtime environment.","Raise fd limits and check memory pressure.","Review container security profiles (seccomp/apparmor) for blocked randomness syscalls.","Restart the host/process; this failure does not recover mid-process."],"exampleFix":"// before\nerr := bm.WriteContent(ctx, data) // fails with 'unable to prepare content preamble'\n// after\nif _, err := rand.Read(make([]byte, 8)); err != nil {\n\tlog.Fatal(\"CSPRNG unavailable, aborting writes: \", err)\n}\nerr := bm.WriteContent(ctx, data)","handlingStrategy":"fallback","validationCode":"b := make([]byte, 8)\nif _, err := cryptorand.Read(b); err != nil {\n\treturn fmt.Errorf(\"CSPRNG unavailable: %w\", err)\n}","typeGuard":"func csprngOK() bool {\n\tb := make([]byte, 4)\n\t_, err := cryptorand.Read(b)\n\treturn err == nil\n}","tryCatchPattern":"if err := bm.WriteContent(ctx, prefix, data); err != nil {\n\tif strings.Contains(err.Error(), \"content preamble\") {\n\t\treturn fmt.Errorf(\"entropy failure on host %q: %w\", hostname, err)\n\t}\n\treturn err\n}","preventionTips":["Health-check randomness at process start.","Use container images with working /dev/urandom.","Do not block getrandom(2) in sandboxes.","Restart processes after any crypto/rand failure."],"tags":["crypto","entropy","write-path"],"backgroundTag":"internal-invariant-violation","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"}