{"record":{"id":"f7a6c6244587cbbf","repo":"hashicorp/nomad","slug":"missing-plugin-id-f7a6c6","errorCode":null,"errorMessage":"missing plugin ID","messagePattern":"missing plugin ID","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/csi_endpoint.go","lineNumber":1910,"sourceCode":"\tv.srv.MeasureRPCRate(\"csi_plugin\", structs.RateMetricRead, args)\n\tif authErr != nil {\n\t\treturn structs.ErrPermissionDenied\n\t}\n\tdefer metrics.MeasureSince([]string{\"nomad\", \"plugin\", \"get\"}, time.Now())\n\n\taclObj, err := v.srv.ResolveACL(args)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif !aclObj.AllowPluginRead() {\n\t\treturn structs.ErrPermissionDenied\n\t}\n\n\tns := args.RequestNamespace()\n\twithAllocs := aclObj.AllowNsOp(ns, acl.NamespaceCapabilityReadJob)\n\n\tif args.ID == \"\" {\n\t\treturn fmt.Errorf(\"missing plugin ID\")\n\t}\n\n\topts := blockingOptions{\n\t\tqueryOpts: &args.QueryOptions,\n\t\tqueryMeta: &reply.QueryMeta,\n\t\trun: func(ws memdb.WatchSet, state *state.StateStore) error {\n\t\t\tsnap, err := state.Snapshot()\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tplug, err := snap.CSIPluginByID(ws, args.ID)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tif plug == nil {\n\t\t\t\treturn nil","sourceCodeStart":1892,"sourceCodeEnd":1928,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/csi_endpoint.go#L1892-L1928","documentation":"Nomad's CSIPlugin.Get RPC looks up a single CSI plugin by ID. When the request's ID field is empty, the endpoint rejects the read up front rather than performing a blocking query with an empty key. It is a strict request-validation error from the client sending an unset plugin ID.","triggerScenarios":"Calling GET /v1/plugin/<id> or nomad plugin status with an empty/omitted plugin ID (e.g. nomad plugin status \"\"), or a client SDK invocation where the plugin ID parameter was left unset.","commonSituations":"Scripting `nomad plugin status $PLUGIN_ID` where the variable is empty because a previous command failed; parsing plugin IDs from templates/CI output that produced a blank string; SDK calls with a zero-value struct.","solutions":["Pass a non-empty plugin ID: nomad plugin status <plugin-id>","List available plugins with nomad node status or GET /v1/plugins to find the correct ID","In scripts, guard the variable: [ -n \"$PLUGIN_ID\" ] || exit 1 before calling the API","In API/SDK calls, ensure args.ID is populated before issuing the request"],"exampleFix":"// before\nPLUGIN_ID=\"\"\nnomad plugin status \"$PLUGIN_ID\"   // missing plugin ID\n\n// after\nPLUGIN_ID=\"aws-ebs-csi-driver\"\n[ -n \"$PLUGIN_ID\" ] && nomad plugin status \"$PLUGIN_ID\"","handlingStrategy":"validation","validationCode":"if pluginID == \"\" {\n    return fmt.Errorf(\"plugin ID required; use GET /v1/plugins to list IDs\")\n}","typeGuard":"func validPluginID(id string) bool { return strings.TrimSpace(id) != \"\" }","tryCatchPattern":"plugin, err := client.CSIPlugins().Get(id)\nif err != nil {\n    if strings.Contains(err.Error(), \"missing plugin ID\") {\n        return nil, fmt.Errorf(\"plugin ID was empty; check script variable\")\n    }\n    return nil, err\n}","preventionTips":["Never interpolate shell variables into plugin commands without a non-empty check","Fetch IDs from GET /v1/plugins instead of hardcoding","Use `set -u` in bash scripts to catch unset variables","Fail fast at script start when an ID variable is blank"],"tags":["validation","csi","nomad","missing-parameter"],"backgroundTag":"missing-required-argument","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"}