{"record":{"id":"66af9468f89c3376","repo":"hashicorp/nomad","slug":"failed-to-parse-config","errorCode":null,"errorMessage":"failed to parse config: ","messagePattern":"failed to parse config: ","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/allocrunner/taskrunner/task_runner.go","lineNumber":945,"sourceCode":"\n\t// Handle per-key errors\n\tif len(errs) > 0 {\n\t\tkeys := make([]string, 0, len(errs))\n\t\tfor k, err := range errs {\n\t\t\tkeys = append(keys, k)\n\n\t\t\tif tr.logger.IsTrace() {\n\t\t\t\t// Verbosely log every diagnostic for debugging\n\t\t\t\ttr.logger.Trace(\"error building environment variables\", \"key\", k, \"error\", err)\n\t\t\t}\n\t\t}\n\n\t\ttr.logger.Warn(\"some environment variables not available for rendering\", \"keys\", strings.Join(keys, \", \"))\n\t}\n\n\tval, diag, diagErrs := hclutils.ParseHclInterface(tr.task.Config, tr.taskSchema, vars)\n\tif diag.HasErrors() {\n\t\tparseErr := multierror.Append(errors.New(\"failed to parse config: \"), diagErrs...)\n\t\ttr.EmitEvent(structs.NewTaskEvent(structs.TaskFailedValidation).SetValidationError(parseErr))\n\t\treturn parseErr\n\t}\n\n\tif err := taskConfig.EncodeDriverConfig(val); err != nil {\n\t\tencodeErr := fmt.Errorf(\"failed to encode driver config: %v\", err)\n\t\ttr.EmitEvent(structs.NewTaskEvent(structs.TaskFailedValidation).SetValidationError(encodeErr))\n\t\treturn encodeErr\n\t}\n\n\t// If there's already a task handle (eg from a Restore) there's nothing\n\t// to do except update state.\n\tif tr.getDriverHandle() != nil {\n\t\t// Ensure running state is persisted but do *not* append a new\n\t\t// task event as restoring is a client event and not relevant\n\t\t// to a task's lifecycle.\n\t\tif err := tr.updateStateImpl(structs.TaskStateRunning); err != nil {\n\t\t\t//TODO return error and destroy task to avoid an orphaned task?","sourceCodeStart":927,"sourceCodeEnd":963,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/client/allocrunner/taskrunner/task_runner.go#L927-L963","documentation":"Nomad's task runner wraps all HCL parsing diagnostics from hclutils.ParseHclInterface into a single multierror prefixed 'failed to parse config: ' when converting a task's raw config into the driver's typed configuration. The trailing colon in the message means the individual HCL diagnostics are appended as sub-errors of the multierror. It is thrown by the task runner's preStart hook path and emitted as a TaskFailedValidation event before the task is started.","triggerScenarios":"tr.task.Config fails hclutils.ParseHclInterface against the driver's taskSchema (hclspecutils-converted spec), e.g. unknown keys, wrong types, missing required fields, or invalid interpolation of template variables in the task's config block.","commonSituations":"Typo'd or unsupported keys in a task's config block after a driver/plugin version change; passing a string where the driver schema expects a number/bool; referencing env vars or node attributes that don't resolve at client-side rendering time; copying config from one driver to another with an incompatible schema.","solutions":["Read the appended hcl.Diagnostics sub-errors in the multierror for the exact offending attribute and fix the task config block","Validate the task config against the driver's TaskConfigSchema (nomad job validate or nomad plan catches most of these client-side)","Check driver version compatibility: schema fields may have been renamed or removed between driver releases","If variables fail to render, fix interpolation syntax or provide the missing variables before the task starts"],"exampleFix":"// before\nconfig {\n  image = \"nginx\"\n  port = \"8080h\"  // invalid: schema expects number\n}\n// after\nconfig {\n  image = \"nginx\"\n  ports = [\"http\"]\n  port  = 8080\n}","handlingStrategy":"validation","validationCode":"// pre-validate the raw task config HCL before submit\n// nomad job validate job.nomad.hcl\nif diag := hclutils.ParseHclInterface(rawCfg, driverSchema, vars); diag.HasErrors() {\n    for _, d := range diag.Errs() {\n        log.Printf(\"config problem: %s\", d)\n    }\n    return fmt.Errorf(\"task config invalid: %s\", errorSummary(diag))\n}","typeGuard":null,"tryCatchPattern":"err := tr.runPreStart()\nif err != nil {\n    var merr *multierror.Error\n    if errors.As(err, &merr) {\n        for _, e := range merr.Errors {\n            log.Printf(\"config error: %v\", e)\n        }\n    }\n    return err\n}","preventionTips":["Always run 'nomad job validate' before submitting jobs","Keep driver configs in sync with the driver plugin's documented schema","Pin driver plugin versions and re-validate configs after upgrades","Use go-cty/hclspec-aware tests for generated task configs"],"tags":["nomad","hcl","config-validation","task-runner"],"backgroundTag":"hcl-config-parse-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"}