{"record":{"id":"2dc272f7f537db0a","repo":"hashicorp/nomad","slug":"error-parsing-keyring-w","errorCode":null,"errorMessage":"error parsing 'keyring': %w","messagePattern":"error parsing 'keyring': %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"command/agent/config_parse.go","lineNumber":103,"sourceCode":"\t\treturn nil, fmt.Errorf(\"error parsing: root should be an object\")\n\t}\n\tmatches := list.Filter(\"vault\")\n\tif len(matches.Items) > 0 {\n\t\tif err := parseVaults(c, matches); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"error parsing 'vault': %w\", err)\n\t\t}\n\t}\n\tmatches = list.Filter(\"consul\")\n\tif len(matches.Items) > 0 {\n\t\tif err := parseConsuls(c, matches); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"error parsing 'consul': %w\", err)\n\t\t}\n\t}\n\n\tmatches = list.Filter(\"keyring\")\n\tif len(matches.Items) > 0 {\n\t\tif err := parseKeyringConfigs(c, matches); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"error parsing 'keyring': %w\", err)\n\t\t}\n\t}\n\n\t// convert strings to time.Durations\n\ttds := []durationConversionMap{\n\t\t{\"gc_interval\", &c.Client.GCInterval, &c.Client.GCIntervalHCL, nil},\n\t\t{\"acl.token_ttl\", &c.ACL.TokenTTL, &c.ACL.TokenTTLHCL, nil},\n\t\t{\"acl.policy_ttl\", &c.ACL.PolicyTTL, &c.ACL.PolicyTTLHCL, nil},\n\t\t{\"acl.policy_ttl\", &c.ACL.RoleTTL, &c.ACL.RoleTTLHCL, nil},\n\t\t{\"acl.token_min_expiration_ttl\", &c.ACL.TokenMinExpirationTTL, &c.ACL.TokenMinExpirationTTLHCL, nil},\n\t\t{\"acl.token_max_expiration_ttl\", &c.ACL.TokenMaxExpirationTTL, &c.ACL.TokenMaxExpirationTTLHCL, nil},\n\t\t{\"client.server_join.retry_interval\", &c.Client.ServerJoin.RetryInterval, &c.Client.ServerJoin.RetryIntervalHCL, nil},\n\t\t{\"server.heartbeat_grace\", &c.Server.HeartbeatGrace, &c.Server.HeartbeatGraceHCL, nil},\n\t\t{\"server.min_heartbeat_ttl\", &c.Server.MinHeartbeatTTL, &c.Server.MinHeartbeatTTLHCL, nil},\n\t\t{\"server.failover_heartbeat_ttl\", &c.Server.FailoverHeartbeatTTL, &c.Server.FailoverHeartbeatTTLHCL, nil},\n\t\t{\"server.plan_rejection_tracker.node_window\", &c.Server.PlanRejectionTracker.NodeWindow, &c.Server.PlanRejectionTracker.NodeWindowHCL, nil},\n\t\t{\"server.retry_interval\", &c.Server.RetryInterval, &c.Server.RetryIntervalHCL, nil},\n\t\t{\"server.server_join.retry_interval\", &c.Server.ServerJoin.RetryInterval, &c.Server.ServerJoin.RetryIntervalHCL, nil},","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/command/agent/config_parse.go#L85-L121","documentation":"ParseConfigFile filters 'keyring' blocks and passes them to parseKeyringConfigs; this error wraps any failure there, such as a keyring provider block not decoding to a map or an extra key not decoding to a string.","triggerScenarios":"Calling ParseConfigFile/LoadConfig on a config with a `keyring { ... }` block that fails parseKeyringConfigs — e.g. provider block not an object/map, or an extra key listed in ExtraKeysHCL whose value is not a string.","commonSituations":"Keyring config with a non-string value like `extra = 42` or `extra = [\"a\"]` where a string is required; malformed keyring stanza copied between versions with different schema.","solutions":["Quote extra key values in the keyring block so they decode as strings: `extra = \"value\"`","Ensure each keyring provider block is an object/map, not a scalar or list","Check the wrapped inner error in the message for the exact failing key","Update the keyring stanza to match the schema expected by your vault/consul version"],"exampleFix":"// before\nkeyring {\n  provider = \"awskms\"\n  region = [\"us-east-1\"]\n}\n\n// after\nkeyring {\n  provider = \"awskms\"\n  region = \"us-east-1\"\n}","handlingStrategy":"validation","validationCode":"func validateKeyringTypes(data []byte) error {\n\troot, err := hcl.Parse(string(data))\n\tif err != nil {\n\t\treturn err\n\t}\n\tlist := root.Node.(*ast.ObjectList).Filter(\"keyring\")\n\tfor _, item := range list.Items {\n\t\tot, ok := item.Val.(*ast.ObjectType)\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"keyring must be a braced block\")\n\t\t}\n\t\t_ = ot // additionally assert each leaf value is a scalar string\n\t}\n\treturn nil\n}","typeGuard":"func keyringValIsString(m map[string]any, key string) bool {\n\t_, ok := m[key].(string)\n\treturn ok\n}","tryCatchPattern":"cfg, err := ParseConfigFile(path)\nif err != nil {\n\tif strings.Contains(err.Error(), \"error parsing 'keyring'\") {\n\t\treturn fmt.Errorf(\"invalid keyring stanza in %s: %w\", path, err)\n\t}\n\treturn err\n}","preventionTips":["Quote all extra key values in keyring blocks so they decode as strings","Keep provider blocks as flat object maps","Check the inner wrapped error for the exact failing key","Keep keyring stanzas in sync with the schema of your vault version"],"tags":["hcl","config-parsing","keyring"],"backgroundTag":"config-value-type-mismatch","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"}