{"record":{"id":"53770d8a9218e2a1","repo":"hashicorp/nomad","slug":"error-parsing-root-should-be-an-object","errorCode":null,"errorMessage":"error parsing: root should be an object","messagePattern":"error parsing: root should be an object","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"acl/policy.go","lineNumber":760,"sourceCode":"\t}\n\n\t// Manually parse the policy to fix blocks without labels.\n\t//\n\t// Due to a bug in the way HCL decodes files, a block without a label may\n\t// return an incorrect key value and make it impossible to determine if the\n\t// key was set by the user or incorrectly set by the decoder.\n\t//\n\t// By manually parsing the file we are able to determine if the label is\n\t// missing in the file and set them to an empty string so the policy\n\t// validation can return the appropriate errors.\n\troot, err := hcl.Parse(rules)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to parse policy: %w\", err)\n\t}\n\n\tlist, ok := root.Node.(*ast.ObjectList)\n\tif !ok {\n\t\treturn errors.New(\"error parsing: root should be an object\")\n\t}\n\n\tnsList := list.Filter(\"namespace\")\n\tfor i, nsObj := range nsList.Items {\n\t\t// Fix missing namespace key.\n\t\tif len(nsObj.Keys) == 0 {\n\t\t\tp.Namespaces[i].Name = \"\"\n\t\t}\n\t\tif i > 0 {\n\t\t\tp.removeExtraKey(\"namespace\")\n\t\t}\n\n\t\t// Fix missing variable paths.\n\t\tnsOT, ok := nsObj.Val.(*ast.ObjectType)\n\t\tif !ok {\n\t\t\tcontinue\n\t\t}\n\t\tvarsList := nsOT.List.Filter(\"variables\")","sourceCodeStart":742,"sourceCodeEnd":778,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/acl/policy.go#L742-L778","documentation":"Nomad's controllerUnpublishVolume (csi_endpoint.go) failed to look up the CSI plugin record for the volume in the state store snapshot via snap.CSIPluginByID. The wrapped error indicates an internal state-store query failure rather than a missing plugin. This is a server-side error during volume unpublish reconciliation.","triggerScenarios":"A volume claim (Unpublish RPC) targets a volume whose PluginID causes the state-store query to return a non-nil error, e.g. during a blocking query/watch error or corrupted snapshot iteration while the server reconciles the claim.","commonSituations":"State store issues on a heavily loaded leader, raft snapshot inconsistencies, or querying during leader elections/failover while unpublish is being retried by the claim runner.","solutions":["Inspect the wrapped inner error (%v) in the Nomad server logs to identify the state-store failure","Retry the unpublish; the claim runner re-invokes controllerUnpublishVolume with backoff","Check server health and raft stability; wait out leader elections before further retries","If persistent, restart the Nomad server and verify state store integrity with nomad operator raft logs"],"exampleFix":"// caller-side: tolerate transient state-store failures during unpublish\n// before\nerr := v.controllerUnpublishVolume(vol, claim, cs)\nif err != nil { return err }\n// after\nerr := v.controllerUnpublishVolume(vol, claim, cs)\nif err != nil && strings.Contains(err.Error(), \"could not query plugin\") {\n    v.logger.Warn(\"transient plugin lookup failure; will retry\", \"vol\", vol.ID)\n    return nil // claim requeued by checkpoint loop\n}\nreturn err","handlingStrategy":"retry","validationCode":"// verify plugin resolvable before triggering unpublish tooling\np, err := api.Plugins().Get(pluginID, nil)\nif err != nil || p == nil { /* re-register plugin first */ }","typeGuard":null,"tryCatchPattern":"if err := unpublish(vol); err != nil && strings.Contains(err.Error(), \"could not query plugin\") {\n    // transient state-store failure: backoff and retry\n    time.Sleep(backoff); retry()\n}","preventionTips":["Keep the Nomad cluster leader-stable before running volume maintenance","Monitor server/raft health metrics","Avoid running unpublish flows during deployments/failovers"],"tags":["nomad","csi","state-store","plugin-lookup"],"backgroundTag":"csi-plugin-lookup-failed","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"}