{"record":{"id":"29c4084b175bb260","repo":"hashicorp/nomad","slug":"connect-proxy-task-must-not-have-a-service-block","errorCode":null,"errorMessage":"Connect proxy task must not have a service block","messagePattern":"Connect proxy task must not have a service block","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/structs.go","lineNumber":8382,"sourceCode":"\tif t.DispatchPayload != nil {\n\t\tif err := t.DispatchPayload.Validate(); err != nil {\n\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"Dispatch Payload validation failed: %v\", err))\n\t\t}\n\t}\n\n\t// Validate the Lifecycle block if there\n\tif t.Lifecycle != nil {\n\t\tif err := t.Lifecycle.Validate(); err != nil {\n\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"Lifecycle validation failed: %v\", err))\n\t\t}\n\n\t}\n\n\t// Validation for TaskKind field which is used for Consul Connect integration\n\tif t.Kind.IsConnectProxy() {\n\t\t// This task is a Connect proxy so it should not have service blocks\n\t\tif len(t.Services) > 0 {\n\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"Connect proxy task must not have a service block\"))\n\t\t}\n\t\tif t.Leader {\n\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"Connect proxy task must not have leader set\"))\n\t\t}\n\n\t\t// Ensure the proxy task has a corresponding service entry\n\t\tserviceErr := ValidateConnectProxyService(t.Kind.Value(), tg.Services)\n\t\tif serviceErr != nil {\n\t\t\tmErr.Errors = append(mErr.Errors, serviceErr)\n\t\t}\n\t}\n\n\t// Validation for volumes\n\tfor idx, vm := range t.VolumeMounts {\n\t\tif _, ok := tg.Volumes[vm.Volume]; !ok {\n\t\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"Volume Mount (%d) references undefined volume %s\", idx, vm.Volume))\n\t\t}\n","sourceCodeStart":8364,"sourceCodeEnd":8400,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/structs.go#L8364-L8400","documentation":"For Consul Connect proxy tasks (task kind is connect-proxy), Task.Validate forbids declaring `service` blocks on the task itself, emitting \"Connect proxy task must not have a service block\". Proxy services are defined at group level and wired automatically by Connect, so per-task services are invalid.","triggerScenarios":"Defining a task with `kind = \"connect-proxy:...\"` (or generated proxy tasks) while also listing `service` blocks inside that task.","commonSituations":"Hand-crafting connect proxy tasks instead of using `connect { sidecar_service {} }`; copying a normal task spec and adding the connect-proxy kind; generated jobs from older tooling.","solutions":["Remove the service blocks from the connect-proxy task","Declare the proxy service via the group's `connect { sidecar_service { proxy {} } }` stanza instead","Let Nomad generate the proxy task rather than writing kind=\"connect-proxy\" manually"],"exampleFix":"// before\ntask \"mesh-proxy\" {\n  kind = \"connect-proxy:api\"\n  service {\n    name = \"api\"\n  }\n}\n// after\ngroup \"api\" {\n  connect {\n    sidecar_service {\n      proxy {}\n    }\n  }\n}","handlingStrategy":"validation","validationCode":"if task.Kind.IsConnectProxy() && len(task.Services) > 0 {\n    return fmt.Errorf(\"connect proxy task %q must not declare services\", task.Name)\n}","typeGuard":"func isConnectProxy(t *structs.Task) bool { return t.Kind.IsConnectProxy() }","tryCatchPattern":"if err := job.Validate(); err != nil {\n    if strings.Contains(err.Error(), \"must not have a service block\") { /* move services to group/connect */ }\n}","preventionTips":["Never hand-write kind=\"connect-proxy\" tasks; use sidecar_service","Keep service blocks at group level for Connect workloads","Validate connect jobs in CI"],"tags":["nomad","connect","consul","service-mesh","validation"],"backgroundTag":"connect-proxy-config-invalid","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"}