hashicorp/nomad · error

failed to stat %s: %v

Error message

failed to stat %s: %v

What it means

RaftStateInfo inspects the Raft state at path p (a BoltDB raft.db file or a WAL directory) and first calls os.Stat on it. This error means the path itself could not be stat'd: it does not exist, a parent directory is missing, or permission is denied. Nothing about the store format is involved yet.

Source

Thrown at helper/raftutil/state.go:41

var (
	errAlreadyOpen = errors.New("unable to open raft logs that are in use")
)

// RaftStore is the interface returned by RaftStateInfo, satisfied by both
// *raftboltdb.BoltStore and *raftwal.WAL.
type RaftStore interface {
	raft.LogStore
	raft.StableStore
	Close() error
}

// RaftStateInfo returns info about the raft state found at path p. The path
// may point to a BoltDB file (raft.db) or a WAL directory. The returned
// RaftStore must be closed by the caller.
func RaftStateInfo(p string) (store RaftStore, firstIdx uint64, lastIdx uint64, err error) {
	info, statErr := os.Stat(p)
	if statErr != nil {
		return nil, 0, 0, fmt.Errorf("failed to stat %s: %v", p, statErr)
	}

	if info.IsDir() {
		return raftStateInfoWAL(p)
	}
	return raftStateInfoBoltDB(p)
}

func raftStateInfoBoltDB(p string) (store RaftStore, firstIdx uint64, lastIdx uint64, err error) {
	opts := raftboltdb.Options{
		Path: p,
		BoltOptions: &bbolt.Options{
			ReadOnly: true,
			Timeout:  1 * time.Second,
		},
		MsgpackUseNewTimeFormat: true,
	}
	s, err := raftboltdb.New(opts)

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Verify the path exists: pass the full path to raft.db (e.g. /var/lib/consul/raft/raft.db) or the WAL directory, not the parent data dir.
  2. Fix permissions: run as a user that can traverse every directory component (often root or the consul service account).
  3. Confirm the node has actually run and created raft state; a fresh node has no raft.db.
  4. Stat the path yourself first (os.Stat / ls -l) and print the OS error to confirm ENOENT vs EACCES.

Example fix

// before
store, _, _, err := raftutil.RaftStateInfo("/var/lib/consul") // wrong: parent dir

// after
p := "/var/lib/consul/raft/raft.db"
if _, err := os.Stat(p); err != nil {
    log.Fatalf("raft state not accessible: %v", err)
}
store, _, _, err := raftutil.RaftStateInfo(p)
Defensive patterns

Strategy: validation

Validate before calling

func mustExist(p string) error {
    if _, err := os.Stat(p); err != nil {
        return fmt.Errorf("raft state path %q not accessible: %w", p, err)
    }
    return nil
}
// call before RaftStateInfo
if err := mustExist(raftPath); err != nil {
    log.Fatal(err)
}

Try / catch

store, _, _, err := raftutil.RaftStateInfo(p)
if err != nil {
    if strings.Contains(err.Error(), "failed to stat") {
        log.Fatalf("path %q missing or unreadable: %v", p, err)
    }
}

Prevention

When it happens

Trigger: os.Stat(p) failing with ENOENT, ENOTDIR, EACCES, or ELOOP when calling RaftStateInfo with a wrong or inaccessible path to raft.db or the WAL directory.

Common situations: Typo in the data dir path (e.g. pointing at the parent data dir instead of raft/), running the tool as a user without permissions on Consul's data dir, or inspecting a node whose raft.db was never created (cluster never bootstrapped).

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/686479ed5abb52fe. Report an issue: GitHub.