hashicorp/nomad · warning
driver updates already batched
Error message
driver updates already batched
What it means
batchDriverUpdates registers the one-shot callback that flushes batched driver node updates, guarded by driversBatched under driversMu. This error indicates a second invocation on the same batchNodeUpdates, which by design supports only a single first-fingerprint driver update flush.
Source
Thrown at client/node_updater.go:476
// used in the driver manager to send driver fingerprints to
func (b *batchNodeUpdates) updateNodeFromDriver(driver string, info *structs.DriverInfo) {
b.driversMu.Lock()
defer b.driversMu.Unlock()
if b.driversBatched {
b.driverCB(driver, info)
return
}
b.drivers[driver] = info
}
// batchDriverUpdates sends all of the batched driver node updates by calling f
// for each driver batched
func (b *batchNodeUpdates) batchDriverUpdates(f drivermanager.UpdateNodeDriverInfoFn) error {
b.driversMu.Lock()
defer b.driversMu.Unlock()
if b.driversBatched {
return fmt.Errorf("driver updates already batched")
}
b.driversBatched = true
for driver, info := range b.drivers {
f(driver, info)
}
return nil
}
// updateNodeFromDevices implements devicemanager.UpdateNodeDevicesFn and is
// used in the device manager to send device fingerprints to
func (b *batchNodeUpdates) updateNodeFromDevices(devices []*structs.NodeDeviceResource) {
b.devicesMu.Lock()
defer b.devicesMu.Unlock()
if b.devicesBatched {
b.devicesCB(devices)
return
}View on GitHub (pinned to 482b49bf1a)
Solutions
- Invoke batchDriverUpdates only once per batchNodeUpdates, during initial client startup
- Instantiate a new batchNodeUpdates for any additional fingerprint round
- Check call flow so reconnect/restart paths construct fresh batchers rather than reusing the startup one
Example fix
// before: retrying batched first fingerprints with same batcher
for round := 0; round < 2; round++ {
b.batchDriverUpdates(fn) // fails on round 1
}
// after: one batcher per round
for round := 0; round < 2; round++ {
b := newBatchNodeUpdates()
b.batchDriverUpdates(fn)
} Defensive patterns
Strategy: try-catch
Validate before calling
if b.driversBatched {
return nil // batch already registered
} Try / catch
if err := b.batchDriverUpdates(fn); err != nil {
if err.Error() == "driver updates already batched" {
logger.Debug("driver batch already registered; ignoring")
return nil
}
return err
} Prevention
- Call batchDriverUpdates once per batchNodeUpdates lifetime only
- Reset/recreate batchers on client restart instead of reusing them
- Keep driver fingerprint batching wired only to initial startup
- Cover startup flow with a test asserting batcher one-shot semantics
When it happens
Trigger: Calling batchNodeUpdates.batchDriverUpdates (directly or via batchFirstFingerprints) more than once on the same batcher instance.
Common situations: Client restart logic that re-triggers batchFirstFingerprints on the original batcher; accidental double registration of the driver manager fingerprinter; tests sharing a batchNodeUpdates across subtests.
Related errors
- host volume updates already batched
- csi updates already batched
- devices updates already batched
- missing accessor ID
- operation on unknown device(s) "%s/%s/%s" (%v): %v
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/4d5294bb5666077c.
Report an issue: GitHub.