hashicorp/nomad · error

cannot specify both deprecated 'raft_boltdb' and 'raft_logst

Error message

cannot specify both deprecated 'raft_boltdb' and 'raft_logstore' blocks; use 'raft_logstore' only

What it means

convertServerConfig rejects a server configuration that supplies both the deprecated top-level raft_boltdb block and the newer raft_logstore block. The new raft_logstore block supersedes raft_boltdb, and specifying both is ambiguous, so the agent fails conversion instead of silently picking one. This check runs at agent start (serverConfig), at reload (handleReload), and in tests of the conversion path.

Source

Thrown at command/agent/agent.go:659

		AdditionalPubKeys: agentConfig.Server.licenseAdditionalPublicKeys,
		LicenseEnvBytes:   agentConfig.Server.LicenseEnv,
		LicensePath:       agentConfig.Server.LicensePath,
		NonProduction:     agentConfig.Server.NonProduction,
	}

	// Add the search configuration
	if search := agentConfig.Server.Search; search != nil {
		conf.SearchConfig = &structs.SearchConfig{
			FuzzyEnabled:  search.FuzzyEnabled,
			LimitQuery:    search.LimitQuery,
			LimitResults:  search.LimitResults,
			MinTermLength: search.MinTermLength,
		}
	}

	// Validate that legacy and new raft config aren't both set
	if agentConfig.Server.RaftBoltConfig != nil && agentConfig.Server.RaftLogStoreConfig != nil {
		return nil, fmt.Errorf("cannot specify both deprecated 'raft_boltdb' and 'raft_logstore' blocks; use 'raft_logstore' only")
	}

	// Set the raft log store parameters. The new raft_logstore block takes
	// precedence, but we still support the deprecated top-level raft_boltdb
	// block for backwards compatibility.
	conf.RaftLogStoreConfig = &nomad.RaftLogStoreConfig{
		Backend:              nomad.LogStoreBackendBoltDB,
		WALSegmentSize:       raftwal.DefaultSegmentSize, // 64MB by default
		VerificationEnabled:  false,
		VerificationInterval: 5 * time.Minute,
	}
	if lsc := agentConfig.Server.RaftLogStoreConfig; lsc != nil {
		if lsc.Backend != "" {
			conf.RaftLogStoreConfig.Backend = lsc.Backend
		}
		conf.RaftLogStoreConfig.DisableLogCache = lsc.DisableLogCache
		if lsc.BoltDB != nil {
			conf.RaftLogStoreConfig.BoltDBNoFreelistSync = lsc.BoltDB.NoFreelistSync

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Remove the deprecated raft_boltdb block and keep only raft_logstore (it takes precedence and is the supported form).
  2. If you must stay on the legacy layout temporarily, remove the raft_logstore block instead.
  3. Audit generated/merged HCL for duplicate raft blocks after config tooling runs.
  4. Restart the agent or SIGHUP reload after cleaning the config.

Example fix

// before
server {
  raft_boltdb {
    data_dir = "/var/lib/nomad"
  }
  raft_logstore {
    store {
      path = "/var/lib/nomad/raft"
    }
  }
}
// after
server {
  raft_logstore {
    store {
      path = "/var/lib/nomad/raft"
    }
  }
}
Defensive patterns

Strategy: validation

Validate before calling

// fail fast if both raft blocks are present in the config source
blocks := countConfigBlocks(hcl, "raft_boltdb", "raft_logstore")
if blocks["raft_boltdb"] > 0 && blocks["raft_logstore"] > 0 {
    return fmt.Errorf("remove deprecated raft_boltdb; keep only raft_logstore")
}

Prevention

When it happens

Trigger: Server config contains both a `raft_boltdb { ... }` block (legacy) and a `raft_logstore { ... }` block simultaneously, during `nomad agent -server` startup or a SIGHUP reload.

Common situations: Migrating to raft_logstore but leaving the old raft_boltdb block commented-in or merged by a config management tool (Chef/Ansible/Puppet) that appends blocks; copying a community example that mixes eras; incremental config upgrades where the old block was forgotten.

Related errors


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