VictoriaMetrics/VictoriaMetrics · error

cannot read %q: %w

Error message

cannot read %q: %w

What it means

ReadFromFile loads persistent queue metainfo (reader/writer offsets) from a JSON file at the given path. This error wraps a non-ENOENT filesystem error returned by os.ReadFile, meaning the file exists but could not be read (permissions, I/O error, path is a directory, etc.). os.IsNotExist errors are returned unwrapped as sentinel behavior; everything else is wrapped here.

Source

Thrown at lib/persistentqueue/persistentqueue.go:662

}

func (mi *metainfo) WriteToFile(path string) error {
	data, err := json.Marshal(mi)
	if err != nil {
		return fmt.Errorf("cannot marshal persistent queue metainfo %#v: %w", mi, err)
	}
	fs.MustWriteAtomic(path, data, true)
	return nil
}

func (mi *metainfo) ReadFromFile(path string) error {
	mi.Reset()
	data, err := os.ReadFile(path)
	if err != nil {
		if os.IsNotExist(err) {
			return err
		}
		return fmt.Errorf("cannot read %q: %w", path, err)
	}
	if err := json.Unmarshal(data, mi); err != nil {
		return fmt.Errorf("cannot unmarshal persistent queue metainfo from %q: %w", path, err)
	}
	if mi.ReaderOffset > mi.WriterOffset {
		return fmt.Errorf("invalid data read from %q: readerOffset=%d cannot exceed writerOffset=%d", path, mi.ReaderOffset, mi.WriterOffset)
	}
	return nil
}

View on GitHub (pinned to 5079fb58f1)

Solutions

  1. Check filesystem permissions on the metainfo file and its directory (ls -l) and ensure the process user can read them
  2. Verify the path points to a regular file, not a directory (file <path>)
  3. Inspect the wrapped OS error (%w) with errors.As(*fs.PathError) to identify errno and address the underlying cause
  4. Check disk health / mount state (dmesg, df) if EIO is reported
  5. If the metainfo file is corrupt or unrecoverable, restore it from backup or recreate the queue directory (data loss may apply)

Example fix

// before: app runs as user 'app', queue dir owned by root
// after:
sudo chown -R app:app /var/lib/vm/queue
chmod 700 /var/lib/vm/queue
Defensive patterns

Strategy: try-catch

Validate before calling

if fi, err := os.Stat(path); err != nil {
    return fmt.Errorf("metainfo inaccessible: %w", err)
} else if !fi.Mode().IsRegular() {
    return fmt.Errorf("%s is not a regular file", path)
} else if file, err := os.Open(path); err != nil {
    return fmt.Errorf("metainfo not readable: %w", err)
} else { file.Close() }

Type guard

func isReadableFile(path string) bool {
    fi, err := os.Stat(path)
    return err == nil && fi.Mode().IsRegular()
}

Try / catch

if err := pq.ReadFromFile(path); err != nil {
    if os.IsNotExist(err) {
        // first run: initialize fresh metainfo
    } else {
        var pe *fs.PathError
        if errors.As(err, &pe) {
            log.Printf("metainfo read failed: op=%s path=%s err=%v", pe.Op, pe.Path, pe.Err)
        }
        return err
    }
}

Prevention

When it happens

Trigger: Calling ReadFromFile(path) (directly or via tryOpeningQueue when opening a FastQueue) where the metainfo file exists but os.ReadFile fails with an error other than fs.ErrNotExist — e.g. EACCES, EISDIR, EIO, device errors.

Common situations: Queue data directory copied with wrong ownership/permissions; metainfo path points at a directory instead of a file; disk or network-mounted storage (NFS) failure; file deleted between existence check and read by another process; running the app as a different user after switching service accounts.

Related errors


AI-assisted analysis of VictoriaMetrics/VictoriaMetrics@5079fb58f1 (2026-09-03). Data as JSON: /api/errors/f754ccb77e33b714. Report an issue: GitHub.