{"record":{"id":"a2f073ec58e7f402","repo":"hashicorp/nomad","slug":"devices-updates-already-batched","errorCode":null,"errorMessage":"devices updates already batched","messagePattern":"devices updates already batched","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"client/node_updater.go","lineNumber":505,"sourceCode":"// used in the device manager to send device fingerprints to\nfunc (b *batchNodeUpdates) updateNodeFromDevices(devices []*structs.NodeDeviceResource) {\n\tb.devicesMu.Lock()\n\tdefer b.devicesMu.Unlock()\n\tif b.devicesBatched {\n\t\tb.devicesCB(devices)\n\t\treturn\n\t}\n\n\tb.devices = devices\n}\n\n// batchDevicesUpdates sends the batched device node updates by calling f with\n// the devices\nfunc (b *batchNodeUpdates) batchDevicesUpdates(f devicemanager.UpdateNodeDevicesFn) error {\n\tb.devicesMu.Lock()\n\tdefer b.devicesMu.Unlock()\n\tif b.devicesBatched {\n\t\treturn fmt.Errorf(\"devices updates already batched\")\n\t}\n\n\tb.devicesBatched = true\n\tf(b.devices)\n\treturn nil\n}\n","sourceCodeStart":487,"sourceCodeEnd":512,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/client/node_updater.go#L487-L512","documentation":"batchDevicesUpdates registers the one-shot callback that flushes batched device node updates, guarded by devicesBatched under devicesMu. This error means the method was called a second time on the same batchNodeUpdates instance, which supports a single device fingerprint flush at client start.","triggerScenarios":"Calling batchNodeUpdates.batchDevicesUpdates (directly or via batchFirstFingerprints) more than once on the same batcher instance.","commonSituations":"Re-running the startup batching sequence after a fingerprint restart or reconnect; duplicated device fingerprinter setup; test suites reusing a single batchNodeUpdates across cases.","solutions":["Call batchDevicesUpdates exactly once per batchNodeUpdates instance","Construct a new batchNodeUpdates for each round that needs device batching","Restructure restart paths so batching is only performed on the initial fingerprint round"],"exampleFix":"// before: batching devices twice on shared batcher\nb.batchDevicesUpdates(fn)\nb.batchDevicesUpdates(fn) // -> \"devices updates already batched\"\n\n// after: guard with fresh instance or flag\nif !b.devicesBatched {\n    b.batchDevicesUpdates(fn)\n} else {\n    b = newBatchNodeUpdates()\n    b.batchDevicesUpdates(fn)\n}","handlingStrategy":"try-catch","validationCode":"if b.devicesBatched {\n\treturn nil // devices already flushed/registered\n}","typeGuard":null,"tryCatchPattern":"if err := b.batchDevicesUpdates(fn); err != nil {\n\tif err.Error() == \"devices updates already batched\" {\n\t\tlogger.Debug(\"devices batch already registered; ignoring\")\n\t\treturn nil\n\t}\n\treturn err\n}","preventionTips":["Register device batching only during the first fingerprint round","Use a new batchNodeUpdates per fingerprint cycle","Avoid duplicate device fingerprinter setup in client construction","Log sentinel already-batched errors instead of failing startup when duplicates are possible"],"tags":["nomad-client","devices","fingerprinting","one-shot"],"backgroundTag":"already-initialized","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}