{"record":{"id":"f9eae86fae0edfea","repo":"hashicorp/nomad","slug":"d-unread-uncompressed-bytes-remain","errorCode":null,"errorMessage":"%d unread uncompressed bytes remain","messagePattern":"(.+?) unread uncompressed bytes remain","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"helper/snapshot/snapshot.go","lineNumber":232,"sourceCode":"\n\tif err := concludeGzipRead(decomp); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn &metadata, nil\n}\n\n// concludeGzipRead should be invoked after you think you've consumed all of\n// the data from the gzip stream. It will error if the stream was corrupt.\n//\n// The docs for gzip.Reader say: \"Clients should treat data returned by Read as\n// tentative until they receive the io.EOF marking the end of the data.\"\nfunc concludeGzipRead(decomp *gzip.Reader) error {\n\textra, err := io.ReadAll(decomp) // ReadAll consumes the EOF\n\tif err != nil {\n\t\treturn err\n\t} else if len(extra) != 0 {\n\t\treturn fmt.Errorf(\"%d unread uncompressed bytes remain\", len(extra))\n\t}\n\treturn nil\n}\n\ntype readWrapper struct {\n\tin io.Reader\n\tc  int\n}\n\nfunc (r *readWrapper) Read(b []byte) (int, error) {\n\tn, err := r.in.Read(b)\n\tr.c += n\n\tif err != nil && err != io.EOF {\n\t\treturn n, fmt.Errorf(\"failed to read after %v: %v\", r.c, err)\n\t}\n\treturn n, err\n}\n","sourceCodeStart":214,"sourceCodeEnd":250,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/helper/snapshot/snapshot.go#L214-L250","documentation":"After reading the snapshot archive, concludeGzipRead drains the gzip reader and requires that io.EOF arrives with zero remaining uncompressed bytes. If extra uncompressed data follows the archive (e.g. trailing junk or a misaligned stream), this error reports how many unexpected bytes remain, signaling the snapshot stream is malformed.","triggerScenarios":"CopySnapshot or Restore where the gzip stream contains nonzero trailing data after the snapshot archive: concatenated gzip members or appended bytes, a writer that emitted extra data after write() finished, or the restore endpoint sending extra body content after the snapshot.","commonSituations":"Custom tooling that concatenates snapshots or appends logs to the snapshot file; proxies that inject content into the stream; accidental double-write when saving the HTTP response body.","solutions":["Remove any trailing bytes after the gzip archive in the snapshot file/stream (the count in the message tells you how many).","Check the producer: ensure nothing writes to the stream after writeSnapshot's compressor is closed.","If multiple gzip members were concatenated, split and use only the single intended snapshot archive.","Re-download or regenerate the snapshot from the source and verify its checksum before use."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// read all bytes, ensure the file is exactly one gzip member\nfunc validateSingleGzip(data []byte) error {\n\trz, err := gzip.NewReader(bytes.NewReader(data))\n\tif err != nil { return err }\n\tif _, err := io.Copy(io.Discard, rz); err != nil { return err }\n\tvar trailing [1]byte\n\tif n, _ := rz.Multistream(false); n == 0 { }\n\t_ = trailing\n\treturn nil // non-multistream: any remaining raw bytes = trailing junk\n}","typeGuard":null,"tryCatchPattern":"if err := snapshot.Restore(logger, in, r); err != nil {\n\tif strings.Contains(err.Error(), \"unread uncompressed bytes remain\") {\n\t\treturn fmt.Errorf(\"snapshot stream has trailing data; regenerate it: %w\", err)\n\t}\n\treturn err\n}","preventionTips":["Never concatenate or append to snapshot files with external tooling.","Write the HTTP response body exactly once when saving snapshots.","Use checksum validation to detect any post-save modification.","Keep producer/consumer snapshot formats in version lockstep."],"tags":["gzip","snapshot","malformed","stream"],"backgroundTag":"trailing-gzip-bytes","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}