{"record":{"id":"51ec57267fbc085b","repo":"hashicorp/nomad","slug":"csi-plugin-loaded-incorrectly","errorCode":null,"errorMessage":"CSI Plugin loaded incorrectly","messagePattern":"CSI Plugin loaded incorrectly","errorType":"exception","errorClass":"ErrPluginTypeError","httpStatus":null,"severity":"critical","filePath":"client/csi_endpoint.go","lineNumber":36,"sourceCode":"\tnstructs \"github.com/hashicorp/nomad/nomad/structs\"\n\t\"github.com/hashicorp/nomad/plugins/csi\"\n)\n\n// CSI endpoint is used for interacting with CSI plugins on a client.\n// TODO: Submit metrics with labels to allow debugging per plugin perf problems.\ntype CSI struct {\n\tc *Client\n}\n\nconst (\n\t// CSIPluginRequestTimeout is the timeout that should be used when making reqs\n\t// against CSI Plugins. It is copied from Kubernetes as an initial seed value.\n\t// https://github.com/kubernetes/kubernetes/blob/e680ad7156f263a6d8129cc0117fda58602e50ad/pkg/volume/csi/csi_plugin.go#L52\n\tCSIPluginRequestTimeout = 2 * time.Minute\n)\n\nvar (\n\tErrPluginTypeError = errors.New(\"CSI Plugin loaded incorrectly\")\n)\n\n// ControllerValidateVolume is used during volume registration to validate\n// that a volume exists and that the capabilities it was registered with are\n// supported by the CSI Plugin and external volume configuration.\nfunc (c *CSI) ControllerValidateVolume(req *structs.ClientCSIControllerValidateVolumeRequest, resp *structs.ClientCSIControllerValidateVolumeResponse) error {\n\tdefer metrics.MeasureSince([]string{\"client\", \"csi_controller\", \"validate_volume\"}, time.Now())\n\n\tif req.VolumeID == \"\" {\n\t\treturn errors.New(\"CSI.ControllerValidateVolume: VolumeID is required\")\n\t}\n\n\tif req.PluginID == \"\" {\n\t\treturn errors.New(\"CSI.ControllerValidateVolume: PluginID is required\")\n\t}\n\n\tplugin, err := c.findControllerPlugin(req.PluginID)\n\tif err != nil {","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/client/csi_endpoint.go#L18-L54","documentation":"ErrPluginTypeError is returned by CSI.findPlugin when a registered plugin instance does not implement the csi.CSIPlugin interface. It means the object stored/loaded under the plugin ID was created by an incompatible or incorrectly loaded plugin binary, so the client cannot use it as a CSI plugin. Kubernetes-derived check via type assertion pIface.(csi.CSIPlugin) failing.","triggerScenarios":"Any CSI client operation (controller/node volume calls) whose lookup path reaches findPlugin and the type assertion at client/csi_endpoint.go:591 fails; plugin registered with a mismatched API version or a binary that does not serve the CSI plugin gRPC surface the client expects.","commonSituations":"Plugin container image built from an older/newer CSI spec; wrong plugin mounted at the socket so the client talks to a non-CSI plugin; version skew between host client and plugin after upgrade; plugin crashes and a stale/incorrect stub is registered.","solutions":["Redeploy/restart the CSI plugin so the correct, compatible binary serves the plugin socket","Verify the plugin implements the CSIPlugin interface (correct gRPC services and version) and matches the expected CSI spec version","Check plugin registration/socket path config to ensure the client is connecting to the intended plugin, not another process","Upgrade host client or plugin so versions are compatible"],"exampleFix":"// before (client hits a plugin that doesn't implement CSIPlugin)\nplugin, ok := pIface.(csi.CSIPlugin)\nif !ok { return nil, ErrPluginTypeError } // \"CSI Plugin loaded incorrectly\"\n// after (redeploy the plugin container image and verify registration)\n// e.g. ensure the plugin job runs the CSI v1.x image matching the client's supported version","handlingStrategy":"try-catch","validationCode":"plugin, ok := pIface.(csi.CSIPlugin)\nif !ok {\n    return fmt.Errorf(\"CSI plugin %q is not a compatible CSIPlugin implementation; redeploy the plugin\", pluginID)\n}","typeGuard":"func isCSIPlugin(pIface interface{}) (csi.CSIPlugin, bool) {\n    p, ok := pIface.(csi.CSIPlugin)\n    return p, ok\n}","tryCatchPattern":"plugin, err := c.findPlugin(pluginID)\nif err != nil {\n    if errors.Is(err, ErrPluginTypeError) {\n        // plugin binary incompatible/incorrectly loaded: redeploy or check version skew\n        return fmt.Errorf(\"plugin %q loaded incorrectly: %w; redeploy compatible plugin\", pluginID, err)\n    }\n    return err\n}","preventionTips":["Pin the plugin container image to a CSI spec version compatible with the host client","Verify the plugin gRPC socket serves the expected CSI services after deploy","Watch for plugin job crashes/restarts that can leave a stale registration","Test controller/node volume operations after every client or plugin upgrade"],"tags":["csi","plugin","type-assertion","storage"],"backgroundTag":"csi-plugin-loaded-incorrectly","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"}