{"record":{"id":"746a14da7317bc2a","repo":"hashicorp/nomad","slug":"csi-controllercreatesnapshot-plugin-did-not-retur","errorCode":null,"errorMessage":"CSI.ControllerCreateSnapshot: plugin did not return error or snapshot","messagePattern":"CSI\\.ControllerCreateSnapshot: plugin did not return error or snapshot","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/csi_endpoint.go","lineNumber":401,"sourceCode":"\t\treturn fmt.Errorf(\"CSI.ControllerCreateSnapshot: %v\", err)\n\t}\n\n\tctx, cancelFn := c.requestContext()\n\tdefer cancelFn()\n\n\t// CSI ControllerCreateSnapshot errors for timeout, codes.Unavailable and\n\t// codes.ResourceExhausted are retried; all other errors are fatal.\n\tcresp, err := plugin.ControllerCreateSnapshot(ctx, csiReq,\n\t\tgrpc_retry.WithPerRetryTimeout(CSIPluginRequestTimeout),\n\t\tgrpc_retry.WithMax(3),\n\t\tgrpc_retry.WithBackoff(grpc_retry.BackoffExponential(100*time.Millisecond)))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"CSI.ControllerCreateSnapshot: %v\", err)\n\t}\n\n\tif cresp == nil || cresp.Snapshot == nil {\n\t\tc.c.logger.Warn(\"plugin did not return error or snapshot; this is a bug in the plugin and should be reported to the plugin author\")\n\t\treturn fmt.Errorf(\"CSI.ControllerCreateSnapshot: plugin did not return error or snapshot\")\n\t}\n\tresp.ID = cresp.Snapshot.ID\n\tresp.ExternalSourceVolumeID = cresp.Snapshot.SourceVolumeID\n\tresp.SizeBytes = cresp.Snapshot.SizeBytes\n\tresp.CreateTime = cresp.Snapshot.CreateTime\n\tresp.IsReady = cresp.Snapshot.IsReady\n\n\treturn nil\n}\n\nfunc (c *CSI) ControllerDeleteSnapshot(req *structs.ClientCSIControllerDeleteSnapshotRequest, resp *structs.ClientCSIControllerDeleteSnapshotResponse) error {\n\tdefer metrics.MeasureSince([]string{\"client\", \"csi_controller\", \"delete_snapshot\"}, time.Now())\n\n\tplugin, err := c.findControllerPlugin(req.PluginID)\n\tif err != nil {\n\t\t// the server's view of the plugin health is stale, so let it know it\n\t\t// should retry with another controller instance\n\t\treturn fmt.Errorf(\"CSI.ControllerDeleteSnapshot: %w: %v\",","sourceCodeStart":383,"sourceCodeEnd":419,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/client/csi_endpoint.go#L383-L419","documentation":"After a successful (err == nil) ControllerCreateSnapshot call, the CSI spec still requires a Snapshot object in the response. If cresp is nil or cresp.Snapshot is nil, the plugin returned success with no data. Nomad explicitly logs that this is a bug in the plugin and returns this error rather than a nil-pointer panic.","triggerScenarios":"Plugin responds to CreateSnapshot with an empty or snapshot-less response despite returning a gRPC OK status — a plugin contract violation.","commonSituations":"Vendor plugin bugs where the snapshot was created but the response object was never populated; plugins handling async snapshot creation incorrectly (returning before filling Snapshot); plugin version regressions.","solutions":["Report the bug to the plugin author, as the log line instructs","Upgrade/downgrade the CSI plugin to a version with correct CreateSnapshot responses","Check whether the snapshot actually exists in the backend before retrying, to avoid duplicates","Recreate the snapshot after fixing/replacing the plugin"],"exampleFix":"// before (plugin side)\nreturn &csi.CreateSnapshotResponse{}, nil\n// after\nreturn &csi.CreateSnapshotResponse{Snapshot: &csi.Snapshot{\n    SnapshotId: id, SourceVolumeId: volID, ReadyToUse: true,\n}}, nil","handlingStrategy":"validation","validationCode":"// Before retrying, check whether the snapshot was actually created in the backend\n// (via cloud console/API or `nomad volume snapshot list`) to avoid duplicate snapshots.\nsnaps := listSnapshotsFromBackend()\nif !contains(snaps, snapshotID) { /* safe to retry create */ }","typeGuard":null,"tryCatchPattern":"// Treat this as a plugin bug, not transient\nif err := c.ControllerCreateSnapshot(req, resp); err != nil {\n    if strings.Contains(err.Error(), \"plugin did not return error or snapshot\") {\n        // verify backend state, then report to plugin vendor\n    }\n}","preventionTips":["Use GA, spec-conformant plugin releases only","Test CreateSnapshot with csc against each new plugin version","Verify snapshots in the backend before retrying creates","Track plugin vendor changelogs for response-shape bug fixes"],"tags":["csi","snapshot","plugin","nil-check"],"backgroundTag":"csi-plugin-invalid-response","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"}