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

  1. Call batchCSIUpdates exactly once per batchNodeUpdates lifetime, from batchFirstFingerprints during client start
  2. Create a new batchNodeUpdates instance for each subsequent batching round
  3. 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

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


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