{"record":{"id":"1fa158dd57d26083","repo":"hashicorp/nomad","slug":"sunexpected-keys-s","errorCode":null,"errorMessage":"%sunexpected keys %s","messagePattern":"(.+?)unexpected keys (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"helper/funcs.go","lineNumber":316,"sourceCode":"\t\t}\n\n\t\t// Search the hcl tags for \"unusedKeys\"\n\t\tunusedKeys := false\n\t\tfor _, p := range tags {\n\t\t\tif p == \"unusedKeys\" {\n\t\t\t\tunusedKeys = true\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tif unusedKeys {\n\t\t\tks, ok := fval.Interface().([]string)\n\t\t\tif ok && len(ks) != 0 {\n\t\t\t\tps := \"\"\n\t\t\t\tif len(path) > 0 {\n\t\t\t\t\tps = strings.Join(path, \".\") + \" \"\n\t\t\t\t}\n\t\t\t\treturn fmt.Errorf(\"%sunexpected keys %s\",\n\t\t\t\t\tps,\n\t\t\t\t\tstrings.Join(ks, \", \"))\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\n// RemoveEqualFold removes the first string that EqualFold matches. It updates xs in place\nfunc RemoveEqualFold(xs *[]string, search string) {\n\tsl := *xs\n\tfor i, x := range sl {\n\t\tif strings.EqualFold(x, search) {\n\t\t\tsl = append(sl[:i], sl[i+1:]...)\n\t\t\tif len(sl) == 0 {\n\t\t\t\t*xs = nil\n\t\t\t} else {\n\t\t\t\t*xs = sl","sourceCodeStart":298,"sourceCodeEnd":334,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/helper/funcs.go#L298-L334","documentation":"unusedKeysImpl walks a struct via reflection (UnusedKeys helper) and reports any leftover keys recorded in []string fields (typically 'unused keys' slices populated by mapstructure WeakDecode). It prefixes the error with the dotted struct path so the caller knows where the unexpected keys were found.","triggerScenarios":"Calling helper.UnusedKeys (or recursive unusedKeysImpl) on a decoded config struct whose 'unused keys' field is non-empty, i.e. the source map/HCL contained keys that did not map to any struct field.","commonSituations":"Users write extra attributes in a job/task config stanza; after decoding, UnusedKeys is run as a strictness check and rejects the config instead of silently ignoring the keys.","solutions":["Remove the listed keys from the input config (they are printed after 'unexpected keys').","Add matching fields to the target struct if the keys are valid but unsupported by the decoder.","If the keys are intentionally ignorable, skip the UnusedKeys check for that struct or clear the unused-keys field."],"exampleFix":"// before\nresources {\n  cpu = 500\n  memeory = 512\n}\n// after\nresources {\n  cpu = 500\n  memory = 512\n}","handlingStrategy":"validation","validationCode":"if errs := helper.UnusedKeys(cfgStruct); errs != nil {\n    return fmt.Errorf(\"config contains unknown fields: %w\", errs)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always run UnusedKeys as a strict-mode check after mapstructure decode","Keep struct fields in sync with documented config surface","Enable decode hooks that error on unknown map keys where possible"],"tags":["reflection","config-validation","go"],"backgroundTag":"unexpected-config-key","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"}