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 development

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Stop/unmount the existing publication (NodeUnpublishVolume or restart the allocation) before republishing with new capabilities.
  2. Make all consumers use a consistent volume capability and read_only setting; update the Nomad job spec to match the existing mount.
  3. Manually unmount and clean the stale target path on the host (umount; verify /proc/mounts) if a previous allocation leaked the mount.
  4. 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

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


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