nats-io/nats-server · error

failed to decompress original block: %w

Error message

failed to decompress original block: %w

What it means

Returned during block recompression when decompressing an already-compressed block with its existing algorithm fails. The block claims a compression algorithm in its metadata but its payload cannot be decompressed, so it cannot be re-encoded to the new algorithm.

Source

Thrown at server/filestore.go:7998

	meta := &CompressionInfo{}
	if _, err := meta.UnmarshalMetadata(origBuf); err != nil {
		// An error is only returned here if there's a problem with parsing
		// the metadata. If the file has no metadata at all, no error is
		// returned and the algorithm defaults to no compression.
		return fmt.Errorf("failed to read existing metadata header: %w", err)
	}
	if meta.Algorithm == alg {
		// The block is already compressed with the chosen algorithm so there
		// is nothing else to do. This is not a common case, it is here only
		// to ensure we don't do unnecessary work in case something asked us
		// to recompress an already compressed block with the same algorithm.
		return nil
	} else if alg != NoCompression {
		// The block is already compressed using some algorithm, so we need
		// to decompress the block using the existing algorithm before we can
		// recompress it with the new one.
		if origBuf, err = meta.Algorithm.Decompress(origBuf); err != nil {
			return fmt.Errorf("failed to decompress original block: %w", err)
		}
	}

	return mb.atomicOverwriteFile(origBuf, true)
}

// Lock should be held.
func (mb *msgBlock) atomicOverwriteFile(buf []byte, allowCompress bool) error {
	if mb.mfd != nil {
		mb.closeFDsLockedNoCheck()
		defer mb.enableForWriting(mb.fs.fip)
	}

	origFN := mb.mfn               // The original message block on disk.
	tmpFN := mb.mfn + blkTmpSuffix // The new block will be written here.

	// Rather than modifying the existing block on disk (which is a dangerous
	// operation if something goes wrong), create a new temporary file. We will

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Check the wrapped cause to identify which algorithm failed to decompress
  2. Verify the running NATS build supports the block's compression algorithm (upgrade if needed)
  3. Restore the block file from backup and retry the algorithm change
  4. If the block is unrecoverable, remove its files and resync/repopulate the stream

Example fix

// broken block compressed with unsupported algorithm
nats-server -v
// upgrade to a build with s2/zstd support, restore block from backup, then:
nats stream update ORDERS --compression=s2
Defensive patterns

Strategy: fallback

Validate before calling

// Go: confirm target algorithm is supported by this build before switching
if !supportedCompression(alg) {
    return fmt.Errorf("build lacks %s support; pick s2 or none", alg)
}

Try / catch

if err != nil && strings.Contains(err.Error(), "failed to decompress original block") {
    log.Printf("block corrupt for recompression: %v", err)
    return restoreBlockFromBackup(blockPath) // fallback path
}

Prevention

When it happens

Trigger: RecompressMsgBlock switching algorithms (e.g. s2 -> zstd) on a block whose compressed payload is corrupt — interrupted earlier compression, truncated file, or bit rot.

Common situations: Server crash mid-compress leaving a half-written block; disk corruption; a block compressed with an algorithm the running binary doesn't support (build flags/version).

Related errors


AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02). Data as JSON: /api/errors/05d46bf9e8ef138c. Report an issue: GitHub.