hashicorp/nomad · warning
csi updates already batched
Error message
csi updates already batched
What it means
batchCSIUpdates registers the one-shot callback that flushes batched CSI plugin node updates, guarded by csiBatched under csiMu. This error means the method was invoked a second time on the same batchNodeUpdates, which is only meant to run once during the first fingerprinting round at client startup.
Source
Thrown at client/node_updater.go:444
// Only one of these is expected to be set, but a future implementation that
// explicitly models monolith plugins with a single fingerprinter may set both
if info.ControllerInfo != nil {
b.csiControllerPlugins[plugin] = info
}
if info.NodeInfo != nil {
b.csiNodePlugins[plugin] = info
}
}
// batchCSIUpdates sends all of the batched CSI updates by calling f for each
// plugin batched
func (b *batchNodeUpdates) batchCSIUpdates(f csimanager.UpdateNodeCSIInfoFunc) error {
b.csiMu.Lock()
defer b.csiMu.Unlock()
if b.csiBatched {
return fmt.Errorf("csi updates already batched")
}
b.csiBatched = true
for plugin, info := range b.csiNodePlugins {
f(plugin, info)
}
for plugin, info := range b.csiControllerPlugins {
f(plugin, info)
}
return nil
}
// updateNodeFromDriver implements drivermanager.UpdateNodeDriverInfoFn and is
// 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 {View on GitHub (pinned to 482b49bf1a)
Solutions
- Call batchCSIUpdates exactly once per batchNodeUpdates lifetime, from batchFirstFingerprints during client start
- Create a new batchNodeUpdates instance for each subsequent batching round
- If re-invocation is legitimate in your flow, tolerate or log this sentinel error instead of failing startup
Example fix
// before: same batcher reused after reconnect
if err := b.batchCSIUpdates(fn); err != nil { /* already batched */ }
// after: reset or recreate batcher on reconnect
b = newBatchNodeUpdates()
if err := b.batchCSIUpdates(fn); err != nil {
return err
} Defensive patterns
Strategy: try-catch
Validate before calling
if b.csiBatched {
return nil // already registered; avoid the sentinel error
} Try / catch
if err := b.batchCSIUpdates(fn); err != nil {
if err.Error() == "csi updates already batched" {
logger.Debug("csi batch already registered; ignoring")
return nil
}
return err
} Prevention
- Invoke batchCSIUpdates only from the single batchFirstFingerprints path
- Recreate the batcher for each fingerprint round
- Don't reuse startup batchers across reconnects
- Add startup tracing to confirm batching runs exactly once
When it happens
Trigger: Calling batchNodeUpdates.batchCSIUpdates (directly or via batchFirstFingerprints) more than once on the same batcher instance, e.g. on client restart/reconnect while reusing the old batcher.
Common situations: Re-running the first-fingerprint batching path after a server reconnect; duplicate wiring of the CSI fingerprinter in client startup; unit tests invoking the batching functions twice on the same struct.
Related errors
- host volume updates already batched
- driver updates already batched
- devices updates already batched
- missing accessor ID
- error parsing: root should be an object
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/6ae0395669afe58e.
Report an issue: GitHub.