{"record":{"id":"f8779f1875596782","repo":"pulumi/pulumi","slug":"encryptedlog-chunk-payload-too-small-d-bytes-n","errorCode":null,"errorMessage":"encryptedlog: chunk payload too small (%d bytes, need at least %d)","messagePattern":"encryptedlog: chunk payload too small \\((.+?) bytes, need at least (.+?)\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/engine/encryptedlog/reader.go","lineNumber":142,"sourceCode":"\t\tif errors.Is(err, io.EOF) || errors.Is(err, io.ErrUnexpectedEOF) {\n\t\t\tcd.done = true\n\t\t\treturn 0, io.EOF\n\t\t}\n\t\treturn 0, fmt.Errorf(\"encryptedlog: reading chunk length: %w\", err)\n\t}\n\tpayloadLen := binary.BigEndian.Uint32(lenBuf[:])\n\tif payloadLen > uint32(maxPayloadLen) {\n\t\treturn 0, fmt.Errorf(\n\t\t\t\"encryptedlog: chunk payload too large (%d bytes)\", payloadLen)\n\t}\n\n\tpayload := make([]byte, payloadLen)\n\tif _, err := io.ReadFull(cd.r, payload); err != nil {\n\t\treturn 0, fmt.Errorf(\"encryptedlog: reading chunk data: %w\", err)\n\t}\n\tminPayload := nonceSize + cd.aesgcm.Overhead()\n\tif len(payload) < minPayload {\n\t\treturn 0, fmt.Errorf(\"encryptedlog: chunk payload too small (%d bytes, need at least %d)\", len(payload), minPayload)\n\t}\n\n\tnonce := payload[:nonceSize]\n\tciphertext := payload[nonceSize:]\n\n\t// Verify the nonce matches the expected counter.\n\tcd.counter++\n\texpected := makeNonce(cd.counter)\n\tif !bytes.Equal(nonce, expected[:]) {\n\t\treturn 0, errors.New(\"encryptedlog: nonce counter mismatch\")\n\t}\n\n\tcompressed, err := cd.aesgcm.Open(nil, nonce, ciphertext, nil)\n\tif err != nil {\n\t\treturn 0, fmt.Errorf(\"encryptedlog: chunk decryption failed: %w\", err)\n\t}\n\n\tgz, err := gzip.NewReader(bytes.NewReader(compressed))","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/pulumi/pulumi/blob/793f7b2e160db4321fb7fb6b0607461e01cb251e/pkg/engine/encryptedlog/reader.go#L124-L160","documentation":"A chunk payload was read but is smaller than the minimum valid frame: a 12-byte GCM nonce plus the 16-byte GCM authentication tag overhead. Such a payload cannot contain both a nonce and authenticated ciphertext, so it is rejected as corrupt.","triggerScenarios":"Reader.Read encounters a chunk whose length prefix declares a payload smaller than nonceSize+aesgcm.Overhead() (28 bytes for AES-256-GCM) — i.e. a malformed or hand-edited PLOG stream.","commonSituations":"Corrupted or truncated log files where the length prefix was read from wrong bytes after a previous desync; manually constructed or tampered PLOG files; reading a file produced by an incompatible writer version.","solutions":["Confirm the file is a genuine PLOG file produced by this writer version (magic/version already validated, so desync implies corruption)","Recover the log from a backup or regenerate it; a corrupted chunk stream cannot be re-synced","Check for tools or scripts that modified the log file in place","File a bug with the producer if you consistently see malformed chunks from a specific writer"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Reject obviously corrupt files up front\nfi, err := os.Stat(plogPath)\nif err != nil {\n\treturn err\n}\nif fi.Size() == 0 {\n\treturn errors.New(\"empty plog file\")\n}","typeGuard":null,"tryCatchPattern":"n, err := reader.Read(buf)\nif err != nil && strings.Contains(err.Error(), \"chunk payload too small\") {\n\t// stop reading: stream is corrupt from this chunk onward\n}","preventionTips":["Never edit PLOG files in place or splice chunks","Only consume logs produced by the same CLI version that wrote them","Keep the file on integrity-checked storage","Validate the magic/version header early and abort on corrupt files"],"tags":["go","encrypted-log","corruption","validation"],"backgroundTag":"corrupt-chunk-frame","analyzedSha":"793f7b2e160db4321fb7fb6b0607461e01cb251e","analyzedAt":"2026-08-31T09:36:43.099Z","schemaVersion":2},"datasetVersion":"2026-09-01T08:17:40.651Z"}