nsqio/nsq · error

failed to read metadata from %s - %s

Error message

failed to read metadata from %s - %s

What it means

nsqd persists its topic/channel metadata to nsqd.dat in --data-path and reads it on startup (loadNsqdMetadata -> readOrEmpty). os.ReadFile on that file returned an error other than 'file does not exist' — e.g. EACCES, EISDIR, I/O error — so the wrapper reports the filename and cause. A clean missing file is intentionally treated as a fresh start and does NOT produce this error.

Source

Thrown at nsqd/nsqd.go:322

	Paused   bool              `json:"paused"`
	Channels []ChannelMetadata `json:"channels"`
}

// ChannelMetadata is the collection of persistent information about a channel.
type ChannelMetadata struct {
	Name   string `json:"name"`
	Paused bool   `json:"paused"`
}

func newMetadataFile(opts *Options) string {
	return path.Join(opts.DataPath, "nsqd.dat")
}

func readOrEmpty(fn string) ([]byte, error) {
	data, err := os.ReadFile(fn)
	if err != nil {
		if !os.IsNotExist(err) {
			return nil, fmt.Errorf("failed to read metadata from %s - %s", fn, err)
		}
	}
	return data, nil
}

func writeSyncFile(fn string, data []byte) error {
	f, err := os.OpenFile(fn, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
	if err != nil {
		return err
	}

	_, err = f.Write(data)
	if err == nil {
		err = f.Sync()
	}
	closeErr := f.Close()
	if err == nil {
		err = closeErr

View on GitHub (pinned to 85cf10c09c)

Solutions

  1. Inspect the file: `ls -l /var/lib/nsqd/nsqd.dat` — if ownership/permissions are wrong, `chown nsqd:nsqd nsqd.dat; chmod 600 nsqd.dat`.
  2. If it is a directory or the volume is mis-mounted, fix the mount so --data-path points at a writable directory.
  3. Check for read-only filesystems: `mount | grep <datapath>`; remount rw or move --data-path to healthy storage.
  4. If the file is corrupt/unreadable and disposable, move it aside (mv nsqd.dat nsqd.dat.bak); nsqd then starts fresh and recreates topics as producers publish.

Example fix

# before
$ ls -l /var/lib/nsqd/nsqd.dat
-rw------- 1 root root 1214 ... nsqd.dat
(nsqd runs as user 'nsqd' -> EACCES)

# after
$ chown nsqd:nsqd /var/lib/nsqd/nsqd.dat
$ systemctl start nsqd
Defensive patterns

Strategy: validation

Validate before calling

// before nsqd startup
info, err := os.Stat(filepath.Join(dataPath, "nsqd.dat"))
if err == nil {
    if info.IsDir() { return errors.New("nsqd.dat is a directory") }
    if f, err := os.OpenFile(filepath.Join(dataPath, "nsqd.dat"), os.O_RDONLY, 0); err != nil {
        return fmt.Errorf("nsqd.dat unreadable: %w", err)
    } else { f.Close() }
}

Prevention

When it happens

Trigger: --data-path readable-listable but nsqd.dat owned by root with 0600 while nsqd runs as the nsqd user; nsqd.dat is a directory (created by accident or a bad volume mount); a read-only or failing disk/volume (NFS stale handle, EIO); SELinux denial on the file.

Common situations: Switching the daemon user (installed as root, later run as 'nsqd'); docker/k8s volume mounts mapping a directory over nsqd.dat path expectations; migrating data between hosts with rsync as root losing ownership; filesystem corruption after an unclean shutdown.

Related errors


AI-assisted analysis of nsqio/nsq@85cf10c09c (2026-08-16). Data as JSON: /api/errors/03e3c4a7d64d608d. Report an issue: GitHub.