{"record":{"id":"17d8158a16a84b1a","repo":"hashicorp/nomad","slug":"volume-max-claims-reached","errorCode":null,"errorMessage":"volume max claims reached","messagePattern":"volume max claims reached","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/errors.go","lineNumber":91,"sourceCode":"\t// Keep the two in sync.\n\tErrResultPaginatorCreation = errors.New(errResultPaginatorCreation)\n\n\tErrUnknownNode = errors.New(ErrUnknownNodePrefix)\n\n\tErrDeploymentTerminalNoCancel    = errors.New(errDeploymentTerminalNoCancel)\n\tErrDeploymentTerminalNoFail      = errors.New(errDeploymentTerminalNoFail)\n\tErrDeploymentTerminalNoPause     = errors.New(errDeploymentTerminalNoPause)\n\tErrDeploymentTerminalNoPromote   = errors.New(errDeploymentTerminalNoPromote)\n\tErrDeploymentTerminalNoResume    = errors.New(errDeploymentTerminalNoResume)\n\tErrDeploymentTerminalNoUnblock   = errors.New(errDeploymentTerminalNoUnblock)\n\tErrDeploymentTerminalNoRun       = errors.New(errDeploymentTerminalNoRun)\n\tErrDeploymentTerminalNoSetHealth = errors.New(errDeploymentTerminalNoSetHealth)\n\tErrDeploymentRunningNoUnblock    = errors.New(errDeploymentRunningNoUnblock)\n\n\tErrCSIClientRPCIgnorable  = errors.New(\"CSI client error (ignorable)\")\n\tErrCSIClientRPCRetryable  = errors.New(\"CSI client error (retryable)\")\n\tErrCSIVolumeMaxClaims     = errors.New(\"volume max claims reached\")\n\tErrCSIVolumeUnschedulable = errors.New(\"volume is currently unschedulable\")\n\tErrCSIPluginInUse         = errors.New(\"plugin in use\")\n)\n\n// IsErrNoLeader returns whether the error is due to there being no leader.\nfunc IsErrNoLeader(err error) bool {\n\treturn err != nil && strings.Contains(err.Error(), errNoLeader)\n}\n\n// IsErrNoRegionPath returns whether the error is due to there being no path to\n// the given region.\nfunc IsErrNoRegionPath(err error) bool {\n\treturn err != nil && strings.Contains(err.Error(), errNoRegionPath)\n}\n\n// IsErrTokenNotFound returns whether the error is due to the passed token not\n// being resolvable.\nfunc IsErrTokenNotFound(err error) bool {\n\treturn err != nil && strings.Contains(err.Error(), errTokenNotFound)","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/errors.go#L73-L109","documentation":"ErrCSIVolumeMaxClaims is returned when a volume claim would exceed the allowed number of concurrent claims — Nomad permits only one writer (or the configured ReadSched/WriteSched reader count) per volume. The state store rejects the Claim RPC when the volume's capacity for concurrent access is exhausted.","triggerScenarios":"Calling CSIVolume.Claim with a write claim while another allocation already holds the write claim, or exceeding max reader claims; observed in isRetryableClaimRPCError and volume claim endpoints/tests.","commonSituations":"Two jobs (or two allocations of one job) both request exclusive access to the same host volume; an old allocation's claim was not released (stale claim) so the new one is rejected; scaling a service that shares a single-writer volume.","solutions":["Release the existing claim (stop the other allocation, or use CSIVolume.Unclaim / 'nomad volume detach <vol> <alloc>') and retry","Configure the volume as multi-writer (csi_plugin/mount_flags with MULTI_NODE_MULTI_WRITER capability) if concurrent writes are truly intended — only if the storage backend supports it","Use volume scaling/clone or a second volume so each writer has its own volume","Verify no orphaned claims from crashed allocations exist (access mode/attachment status in 'nomad volume status') and clean them up"],"exampleFix":"// before\njob uses volume \"data\" with access_mode = \"single-node-writer\" on 2 allocations\n// after\n# either run a single writer allocation, or declare the volume with\n# capability MULTI_NODE_MULTI_WRITER and access_mode = \"multi-node-multi-writer\"\nvolume \"data\" {\n  type   = \"csi\"\n  source = \"data\"\n  access_mode     = \"multi-node-multi-writer\"\n  attachment_mode = \"file-system\"\n}","handlingStrategy":"validation","validationCode":"vol, _, _ := client.CSIVolumes().Info(volID, nil)\nif vol != nil {\n    for _, a := range vol.Allocations {\n        if a.Mode == \"single-node-writer\" {\n            return fmt.Errorf(\"volume %s write claim held by alloc %s\", volID, a.ID)\n        }\n    }\n}","typeGuard":"func volumeWritable(vol *api.CSIVolume) bool {\n    return vol != nil && vol.WriteAllocs != nil && len(vol.WriteAllocs) == 0\n}","tryCatchPattern":"err := claimVolume(volID, allocID)\nif err != nil && strings.Contains(err.Error(), structs.ErrCSIVolumeMaxClaims.Error()) {\n    return fmt.Errorf(\"volume %s already claimed; unclaim or provision another\", volID)\n}","preventionTips":["Ensure only one allocation requests write access per single-writer volume","Release claims (volume detach/deregister) when allocations are recycled","Provision per-consumer volumes or use multi-writer capabilities where supported","Check 'nomad volume status' for existing claims before scheduling writers"],"tags":["csi","storage","nomad","claim-limit"],"backgroundTag":"volume-max-claims-reached","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"}