{"record":{"id":"c425ea95ba17683c","repo":"hashicorp/nomad","slug":"service-provider-must-be-q-or-q-not-q","errorCode":null,"errorMessage":"Service provider must be %q, or %q; not %q","messagePattern":"Service provider must be %q, or %q; not %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/services.go","lineNumber":800,"sourceCode":"\t}\n\n\tswitch s.OnUpdate {\n\tcase \"\", OnUpdateIgnore, OnUpdateRequireHealthy, OnUpdateIgnoreWarn:\n\t\t// OK\n\tdefault:\n\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"Service on_update must be %q, %q, or %q; not %q\", OnUpdateRequireHealthy, OnUpdateIgnoreWarn, OnUpdateIgnore, s.OnUpdate))\n\t}\n\n\t// Up until this point, all service validation has been independent of the\n\t// provider. From this point on, we have different validation paths. We can\n\t// also catch an incorrect provider parameter.\n\tswitch s.Provider {\n\tcase ServiceProviderConsul:\n\t\ts.validateConsulService(&mErr)\n\tcase ServiceProviderNomad:\n\t\ts.validateNomadService(&mErr)\n\tdefault:\n\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"Service provider must be %q, or %q; not %q\",\n\t\t\tServiceProviderConsul, ServiceProviderNomad, s.Provider))\n\t}\n\n\tif err := s.validateIdentity(); err != nil {\n\t\tmErr.Errors = append(mErr.Errors, err)\n\t}\n\n\treturn mErr.ErrorOrNil()\n}\n\n// MakeUniqueIdentityName returns a service identity name consisting of: task\n// name, service name and service port label.\nfunc (s *Service) MakeUniqueIdentityName() string {\n\tprefix := ConsulServiceIdentityNamePrefix\n\tif s.Provider == ServiceProviderNomad {\n\t\tprefix = \"nomad-service\"\n\t}\n\tif s.TaskName != \"\" {","sourceCodeStart":782,"sourceCodeEnd":818,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/services.go#L782-L818","documentation":"This error is thrown by Service.Validate in nomad/structs/services.go when a service's `provider` field is neither \"consul\" nor \"nomad\". Nomad only supports these two service providers, so any other value fails validation before the job is submitted. It typically indicates a typo or an unsupported provider value in the service stanza.","triggerScenarios":"Submitting a job whose service stanza sets provider to any string other than ServiceProviderConsul (\"consul\") or ServiceProviderNomad (\"nomad\") — e.g. provider = \"consul1\", \"Consul\" (case handled via enum constants), \"\", or a misspelled value.","commonSituations":"Typo in the provider field; copying configs from tools that use different provider names; leaving provider empty when the job/cluster expects an explicit provider; upgrading Nomad where the default provider semantics changed.","solutions":["Set provider = \"consul\" in the service stanza to register with Consul.","Set provider = \"nomad\" in the service stanza to use Nomad's native service discovery.","Remove the provider field if you want the cluster default and verify the cluster's default via the provider allow/deny list in agent config."],"exampleFix":"// before\nservice {\n  name = \"web\"\n  provider = \"Consul\"\n}\n// after\nservice {\n  name = \"web\"\n  provider = \"consul\"\n}","handlingStrategy":"validation","validationCode":"func validProvider(p string) bool { return p == \"consul\" || p == \"nomad\" }\nif !validProvider(svc.Provider) { return fmt.Errorf(\"provider %q must be consul or nomad\", svc.Provider) }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always set provider explicitly to \"consul\" or \"nomad\" in service stanzas","Use HCL constants/variables for provider names instead of free-text strings","Run `nomad job validate` before submitting jobs in CI"],"tags":["nomad","service-discovery","validation","config"],"backgroundTag":"invalid-service-provider","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"}