nats-io/nats-server · error

failed to read original block from disk: %w

Error message

failed to read original block from disk: %w

What it means

Returned during block recompression when reading the original block file (os.ReadFile on mb.mfn) fails inside a Dioscuri (dios) critical section. Recompression must load the full block into memory to decrypt/decompress and rewrite it; if the file cannot be read, the operation aborts with this wrapper.

Source

Thrown at server/filestore.go:7968

	// If the block has been closed in the meantime, skip.
	if mb.closed {
		return nil
	}

	alg := mb.fs.fcfg.Compression

	// Open up the file block and read in the entire contents into memory.
	// One of two things will happen:
	// 1. The block will be compressed already and have a valid metadata
	//    header, in which case we do nothing.
	// 2. The block will be uncompressed, in which case we will compress it
	//    and then write it back out to disk, re-encrypting if necessary.
	mb.fs.dios.acquire()
	origBuf, err := os.ReadFile(mb.mfn)
	mb.fs.dios.release()

	if err != nil {
		return fmt.Errorf("failed to read original block from disk: %w", err)
	}

	// If the block is encrypted then we will need to decrypt it before
	// doing anything. We always encrypt after compressing because then the
	// compression can be as efficient as possible on the raw data, whereas
	// the encrypted ciphertext will not compress anywhere near as well.
	// The block encryption also covers the optional compression metadata.
	if err = mb.encryptOrDecryptIfNeeded(origBuf); err != nil {
		return err
	}

	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)
	}

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Check the wrapped cause: verify the block file exists and is readable by the server user
  2. Free disk space / repair the mount before retrying compression
  3. Ensure no external jobs delete files under the jetstream directory
  4. Retry UpdateStream with the compression setting after storage is healthy

Example fix

// before: failing recompress on missing file
ls -l /path/jetstream/$ACC/streams/ORDERS/msgblk/3.blk
# restore the file from backup, then re-run:
nats stream update ORDERS --compression=s2
Defensive patterns

Strategy: retry

Validate before calling

// Go: verify the block file is readable before recompression
f, err := os.Open(blockPath)
if err != nil {
    return fmt.Errorf("block unreadable, skip compression change: %w", err)
}
f.Close()

Try / catch

err := js.UpdateStream(ctx, cfg) // compression change triggers recompress
if err != nil && strings.Contains(err.Error(), "failed to read original block") {
    if transientStorageErr(err) {
        time.Sleep(retryBackoff)
        return js.UpdateStream(ctx, cfg) // retry after mount/space restored
    }
    return err
}

Prevention

When it happens

Trigger: Calling stream/block recompression APIs (e.g. UpdateStream with a new compression algorithm) where the .blk file is unreadable — deleted, permission changed, or I/O error on the underlying device.

Common situations: Storage volume detached or full mid-operation; file removed by external cleanup scripts; running with a read-only filesystem; block file too large to read into available memory (OOM-adjacent failure).

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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