{"record":{"id":"e0228a29545575d6","repo":"hashicorp/nomad","slug":"service-s-failed-validation-v","errorCode":null,"errorMessage":"service (%s) failed validation: %v","messagePattern":"service \\((.+?)\\) failed validation: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/allocrunner/taskrunner/validate_hook.go","lineNumber":65,"sourceCode":"\n\t// Validate the user\n\t// COMPAT(1.0) uses inclusive language. blacklist is kept for backward compatilibity.\n\tunallowedUsers := conf.ReadStringListAlternativeToMapDefault(\n\t\t[]string{\"user.denylist\", \"user.blacklist\"},\n\t\tconfig.DefaultUserDenylist,\n\t)\n\tcheckDrivers := conf.ReadStringListToMapDefault(\"user.checked_drivers\", config.DefaultUserCheckedDrivers)\n\tif _, driverMatch := checkDrivers[task.Driver]; driverMatch {\n\t\tif _, unallowed := unallowedUsers[task.User]; unallowed {\n\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"running as user %q is disallowed\", task.User))\n\t\t}\n\t}\n\n\t// Validate the Service names once they're interpolated\n\tfor _, service := range task.Services {\n\t\tname := taskEnv.ReplaceEnv(service.Name)\n\t\tif err := service.ValidateName(name); err != nil {\n\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"service (%s) failed validation: %v\", name, err))\n\t\t}\n\t}\n\n\tif len(mErr.Errors) == 1 {\n\t\treturn mErr.Errors[0]\n\t}\n\treturn mErr.ErrorOrNil()\n}\n","sourceCodeStart":47,"sourceCodeEnd":74,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/client/allocrunner/taskrunner/validate_hook.go#L47-L74","documentation":"After environment interpolation, each service name on the task is validated via service.ValidateName. Names must be valid per Nomad/Consul naming rules (alphanumeric plus dashes, no illegal characters, length limits). Failures are collected into a multi-error prefixed with this message.","triggerScenarios":"A service's Name (after taskEnv.ReplaceEnv interpolation) contains invalid characters, is empty because an interpolated variable was undefined, or violates Consul service-name constraints.","commonSituations":"Using service names with underscores, dots, or slashes; service name built from an env var like ${NAMESPACE} that renders empty or with invalid characters; copy-pasting Kubernetes-style names into Nomad services.","solutions":["Rename the service to use only valid characters (letters, digits, dashes)","Check that any env vars used in the name are defined in the task's env block","Fix interpolation so the name does not resolve empty","Read the wrapped error after the prefix — it names the exact rule violated"],"exampleFix":"// before\nservice { name = \"${NOMAD_JOB_NAME}_api\" }\n// after\nservice { name = \"${NOMAD_JOB_NAME}-api\" }","handlingStrategy":"validation","validationCode":"// pre-check interpolated service names\nfor _, svc := range task.Services {\n    name := taskEnv.ReplaceEnv(svc.Name)\n    if err := structs.ValidateServiceName(name); err != nil {\n        return fmt.Errorf(\"service %q invalid: %w\", svc.Name, err)\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := service.ValidateName(name); err != nil {\n    // err names the violated rule (chars, length, emptiness)\n    return fmt.Errorf(\"rename service %q — only alphanumerics and dashes allowed: %w\", name, err)\n}","preventionTips":["Use dashes, not underscores, in service names","Ensure every ${VAR} inside a service name is defined in the task's env block","Keep service names short and static; avoid heavy interpolation","Validate job files with nomad job validate before submitting"],"tags":["service","validation","consul","naming"],"backgroundTag":"service-name-validation-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"}