{"record":{"id":"58252d582409512e","repo":"hashicorp/nomad","slug":"structs-errunknownallocationprefix","errorCode":null,"errorMessage":"structs.ErrUnknownAllocationPrefix","messagePattern":"structs\\.ErrUnknownAllocationPrefix","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/state/state_store.go","lineNumber":2892,"sourceCode":"\trow, err := txn.First(TableCSIVolumes, \"id\", namespace, id)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"volume lookup failed: %s: %v\", id, err)\n\t}\n\tif row == nil {\n\t\treturn fmt.Errorf(\"volume not found: %s\", id)\n\t}\n\n\torig, ok := row.(*structs.CSIVolume)\n\tif !ok {\n\t\treturn fmt.Errorf(\"volume row conversion error\")\n\t}\n\n\tvar alloc *structs.Allocation\n\tif claim.State == structs.CSIVolumeClaimStateTaken {\n\t\talloc, err = s.allocByIDImpl(txn, nil, claim.AllocationID)\n\t\tif err != nil {\n\t\t\ts.logger.Error(\"AllocByID failed\", \"error\", err)\n\t\t\treturn fmt.Errorf(structs.ErrUnknownAllocationPrefix)\n\t\t}\n\t\tif alloc == nil {\n\t\t\ts.logger.Error(\"AllocByID failed to find alloc\", \"alloc_id\", claim.AllocationID)\n\t\t}\n\t}\n\n\tvolume, err := s.csiVolumeDenormalizePluginsTxn(txn, orig.Copy())\n\tif err != nil {\n\t\treturn err\n\t}\n\tvolume, err = s.csiVolumeDenormalizeTxn(txn, nil, volume)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// In the case of a job deregistration, there will be no allocation ID\n\t// for the claim but we still want to write an updated index to the volume\n\t// so that volume reaping is triggered","sourceCodeStart":2874,"sourceCodeEnd":2910,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/state/state_store.go#L2874-L2910","documentation":"When a CSI volume claim with state 'taken' references an allocation, the state store looks it up with allocByIDImpl inside the same transaction. If that lookup returns a database error (not merely nil), the store wraps the shared sentinel structs.ErrUnknownAllocationPrefix and aborts the claim. It means the allocation the claim depends on could not be read from state.","triggerScenarios":"CSIVolumeClaim with claim.State == CSIVolumeClaimStateTaken and a non-empty AllocationID while the alloc table lookup fails — e.g. memdb I/O error, transaction corruption, or a Raft entry applied against inconsistent state.","commonSituations":"Corrupted Nomad server state; claims replayed from raft logs after a partial snapshot restore; storage backend (BoltDB) issues on disk-full conditions.","solutions":["Check server logs for the accompanying 'AllocByID failed' error with the underlying cause","Verify disk health and free space on the server data_dir (BoltDB errors are common when disk is full)","Restart the Nomad server and, if state is persistently corrupt, restore from a known-good raft snapshot","Re-run the job/alloc so a fresh claim is created against an existing allocation"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Verify the allocation exists before issuing a claim\nalloc, _, err := client.Allocations().Info(claim.AllocationID, nil)\nif err != nil || alloc == nil {\n\treturn fmt.Errorf(\"alloc %s not found; cannot claim volume\", claim.AllocationID)\n}","typeGuard":"func allocExists(a *api.Allocation) bool { return a != nil && a.ID != \"\" }","tryCatchPattern":"err := client.CSIVolumes().Claim(claim)\nif err != nil && strings.Contains(err.Error(), structs.ErrUnknownAllocationPrefix) {\n\t// alloc lookup failed: re-resolve alloc or re-run job\n}","preventionTips":["Ensure the allocation ID passed in claims is live before claiming","Watch for disk-full on Nomad servers (BoltDB)","Re-run claims after snapshot restores complete","Alert on 'AllocByID failed' server logs"],"tags":["go","state-store","csi","nomad","allocation"],"backgroundTag":"unknown-allocation","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"}