hashicorp/nomad · error

failed to open raft logs: %v

Error message

failed to open raft logs: %v

What it means

raftStateInfoBoltDB opens the BoltDB-backed Raft log via raftboltdb.New(opts). This error wraps any open failure except the special 'timeout' case (mapped to errAlreadyOpen). Typical causes are file corruption, wrong file type, or I/O problems — i.e., the file exists but could not be opened as a Raft BoltDB store.

Source

Thrown at helper/raftutil/state.go:64

	}
	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)
	if err != nil {
		if strings.HasSuffix(err.Error(), "timeout") {
			return nil, 0, 0, errAlreadyOpen
		}
		return nil, 0, 0, fmt.Errorf("failed to open raft logs: %v", err)
	}

	firstIdx, err = s.FirstIndex()
	if err != nil {
		return nil, 0, 0, fmt.Errorf("failed to fetch first index: %v", err)
	}

	lastIdx, err = s.LastIndex()
	if err != nil {
		return nil, 0, 0, fmt.Errorf("failed to fetch last index: %v", err)
	}

	return s, firstIdx, lastIdx, nil
}

func raftStateInfoWAL(p string) (store RaftStore, firstIdx uint64, lastIdx uint64, err error) {
	s, err := raftwal.Open(p)
	if err != nil {

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Confirm the file is the BoltDB raft.db (first bytes are BoltDB magic 0xED0CDAED), not a WAL file or another DB.
  2. Stop Consul or copy the file cleanly (consul snapshot backup or filesystem-consistent copy) and inspect the copy instead of a live/torn one.
  3. If corruption is indicated, restore raft state from a verified snapshot rather than trying to open the damaged DB.
  4. Check filesystem mounts and permissions; ensure the path is writable if the tool opens read-write.
  5. If you actually hit a lock 'timeout' error, a store is already open — that surfaces as errAlreadyOpen, not this message.

Example fix

// before
store, _, _, err := raftutil.RaftStateInfo("/var/lib/consul/raft/raft.db") // live, torn copy

// after
// stop the agent or take a consistent copy first
cmd := exec.Command("cp", "--reflink=auto", raftDB, workCopy)
if err := cmd.Run(); err != nil {
    log.Fatal(err)
}
store, _, _, err := raftutil.RaftStateInfo(workCopy)
Defensive patterns

Strategy: validation

Validate before calling

func isBoltDBFile(p string) (bool, error) {
    f, err := os.Open(p)
    if err != nil {
        return false, err
    }
    defer f.Close()
    magic := make([]byte, 4)
    if _, err := io.ReadFull(f, magic); err != nil {
        return false, err
    }
    return bytes.Equal(magic, []byte{0xED, 0x0C, 0xDA, 0xED}), nil
}

Try / catch

store, _, _, err := raftutil.RaftStateInfo(raftDB)
if err != nil {
    if errors.Is(err, raftutil.ErrAlreadyOpen) {
        log.Printf("store already open elsewhere")
    } else if strings.Contains(err.Error(), "failed to open raft logs") {
        log.Printf("raft.db corrupt or wrong file type: %v", err)
    }
}

Prevention

When it happens

Trigger: raftboltdb.New failing on the given raft.db path: file is not a BoltDB database, BoltDB freelist/meta corruption, snapshot-in-progress or lock-file contention (non-timeout errors), or read-only filesystem. Note: 'timeout' suffix errors are reported as errAlreadyOpen instead of this message.

Common situations: Pointing the tool at a WAL file or an unrelated file named raft.db, inspecting raft.db from a node that crashed mid-write, copying raft.db while Consul was running (torn copy), or a filesystem mounted read-only.

Related errors


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