hashicorp/nomad · error
volume %q is already published at target path %q but with ca
Error message
volume %q is already published at target path %q but with capabilities or a read_only setting incompatible with this request: %v
What it means
NodePublishVolume wraps gRPC AlreadyExists errors with this message. The volume is already mounted at the target path, but the existing mount's volume capability (ACCESS_MODE, MULTI_NODE setting) or read_only flag differs from what the current request asks for, so the CSI spec forbids reusing it.
Source
Thrown at plugins/csi/client.go:876
func (c *client) NodePublishVolume(ctx context.Context, req *NodePublishVolumeRequest, opts ...grpc.CallOption) error {
if err := c.ensureConnected(ctx); err != nil {
return err
}
if err := req.Validate(); err != nil {
return fmt.Errorf("validation error: %v", err)
}
// NodePublishVolume's response contains no extra data. If err == nil, we were
// successful.
_, err := c.nodeClient.NodePublishVolume(ctx, req.ToCSIRepresentation(), opts...)
if err != nil {
code := status.Code(err)
switch code {
case codes.NotFound:
err = fmt.Errorf("volume %q could not be found: %v", req.ExternalID, err)
case codes.AlreadyExists:
err = fmt.Errorf(
"volume %q is already published at target path %q but with capabilities or a read_only setting incompatible with this request: %v",
req.ExternalID, req.TargetPath, err)
case codes.FailedPrecondition:
err = fmt.Errorf("volume %q does not have MULTI_NODE volume capability: %v",
req.ExternalID, err)
case codes.Internal:
err = fmt.Errorf("node plugin returned an internal error, check the plugin allocation logs for more information: %v", err)
}
}
return err
}
func (c *client) NodeUnpublishVolume(ctx context.Context, volumeID, targetPath string, opts ...grpc.CallOption) error {
if err := c.ensureConnected(ctx); err != nil {
return err
}
// These errors should not be returned during production use but exist as aids
// during Nomad developmentView on GitHub (pinned to 482b49bf1a)
Solutions
- Stop/unmount the existing publication (NodeUnpublishVolume or restart the allocation) before republishing with new capabilities.
- Make all consumers use a consistent volume capability and read_only setting; update the Nomad job spec to match the existing mount.
- Manually unmount and clean the stale target path on the host (umount; verify /proc/mounts) if a previous allocation leaked the mount.
- If needed, detach/unpublish from the storage side and retry publish with the desired capabilities.
Example fix
// before: republishing with a different access mode at a live mount
req.VolumeCapability.AccessMode.Mode = csipbv1.VolumeCapability_AccessMode_MULTI_NODE_MULTI_WRITER
c.NodePublishVolume(ctx, req)
// after: unpublish then republish consistently
if err := c.NodeUnpublishVolume(ctx, volumeID, targetPath); err != nil { return err }
req.VolumeCapability.AccessMode.Mode = csipbv1.VolumeCapability_AccessMode_MULTI_NODE_MULTI_WRITER
return c.NodePublishVolume(ctx, req) Defensive patterns
Strategy: validation
Validate before calling
// before publishing, verify no existing mount with different capabilities
if mountedAt(targetPath) && existingMode != req.Capability.AccessMode.Mode {
return fmt.Errorf("unpublish existing mount at %s before republishing", targetPath)
} Type guard
func isCSIAlreadyExists(err error) bool { return status.Code(err) == codes.AlreadyExists } Try / catch
if err := client.NodePublishVolume(ctx, req); err != nil && strings.Contains(err.Error(), "already published") {
_ = client.NodeUnpublishVolume(ctx, req.ExternalID, req.TargetPath)
return client.NodePublishVolume(ctx, req) // republish with consistent caps
} Prevention
- Keep volume capability and read_only settings identical across all consumers of a volume.
- Don't change access modes while allocations using the volume are running.
- Clean stale mounts on host drain/restart before rescheduling.
When it happens
Trigger: Calling NodePublishVolume for a volume already published at req.TargetPath when the new request's VolumeCapability or RO flag is incompatible with the existing publication (codes.AlreadyExists).
Common situations: A task group spec changed a volume's access mode (e.g. SINGLE_NODE_WRITER -> MULTI_NODE_MULTI_WRITER) or mount flags while the old mount remained; leftover mount from a previous allocation at the same host path; accidentally publishing the same volume with different read_only settings to the same target path.
Related errors
- CSI.ControllerValidateVolume: VolumeID is required
- nil response from plugin.NodeExpandVolume
- volume clone ID cannot be updated
- volume snapshot ID cannot be updated
- volume requested capabilities update was not compatible with
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/02bd0bf49d4e8b56.
Report an issue: GitHub.