{"record":{"id":"4e440e7668f46149","repo":"hashicorp/nomad","slug":"service-q-contains-invalid-check-agent-checks-do","errorCode":null,"errorMessage":"service %q contains invalid check: agent checks do not support scripts","messagePattern":"service %q contains invalid check: agent checks do not support scripts","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"command/agent/consul/service_client.go","lineNumber":1261,"sourceCode":"\n\t\t// older agents use SHA-1 hashes as part of the service name instead of\n\t\t// SHA-256, but we can't guarantee they've shutdown gracefully and\n\t\t// deregistered themselves on upgrade. Remove any legacy service IDs\n\t\t// that might be lingering\n\t\t//\n\t\t// COMPAT: remove once upgrades from pre-FIPS-compatible agents are no longer\n\t\t// supported. Upgrading agents in-place to FIPS-enabled is unsupported.\n\t\tlegacyID := service.LegacyAgentID(role)\n\t\tif legacyID != \"\" {\n\t\t\t// we intentionally swallow this error because these services likely\n\t\t\t// no longer exist\n\t\t\t_ = c.agentAPI.ServiceDeregisterOpts(legacyID, nil)\n\t\t}\n\n\t\tfor _, check := range service.Checks {\n\t\t\tcheckID := MakeCheckID(id, check)\n\t\t\tif check.Type == structs.ServiceCheckScript {\n\t\t\t\treturn fmt.Errorf(\"service %q contains invalid check: agent checks do not support scripts\", service.Name)\n\t\t\t}\n\t\t\tcheckHost, checkPort := serviceReg.Address, serviceReg.Port\n\t\t\tif check.PortLabel != \"\" {\n\t\t\t\t// Unlike tasks, agents don't use port labels. Agent ports are\n\t\t\t\t// stored directly in the PortLabel.\n\t\t\t\thost, rawport, err := net.SplitHostPort(check.PortLabel)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"error parsing port label %q from check %q: %v\", service.PortLabel, check.Name, err)\n\t\t\t\t}\n\t\t\t\tport, err := strconv.Atoi(rawport)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"error parsing port %q from check %q: %v\", rawport, check.Name, err)\n\t\t\t\t}\n\t\t\t\tcheckHost, checkPort = host, port\n\t\t\t}\n\t\t\tcheckReg, err := createCheckReg(id, checkID, check, checkHost, checkPort, \"\")\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to add check %q: %v\", check.Name, err)","sourceCodeStart":1243,"sourceCodeEnd":1279,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/command/agent/consul/service_client.go#L1243-L1279","documentation":"Nomad's Consul client builds agent-side service registrations by looping over each check on a service. Script checks (check.Type == structs.ServiceCheckScript) require the Nomad task driver to execute, but agent services are registered directly with the local Consul agent, which has no Nomad task context to run a script. The code therefore rejects the whole service registration with this error instead of registering a check Consul cannot run.","triggerScenarios":"Calling agent service registration (serviceClient.RegisterAgentWorkload, invoked when an agent registers its own services like 'Nomad Client' HTTP/RPC services or via client config) with a check whose Type is 'script'. Happens when agent config or a client 'check' block sets check type to script, or a driver-network/agent path passes a templated check that resolved to a script type.","commonSituations":"Copying a task-level check block with `type = \"script\"` into the Nomad agent's client config; a version upgrade where check types are derived differently; misconfigured check_template producing a script check on an agent service.","solutions":["Remove the script check or change its type to 'http' or 'tcp' for agent services (agent checks only support http/tcp/grpc-style non-script checks)","If script execution is required, move the service and check into a job's task group (task-level service registration) instead of agent config","Verify with `consul services` / agent logs which check carried type script and fix the source config block","Upgrade/align Nomad versions if a Nomad-generated agent check unexpectedly contains a script type"],"exampleFix":"// before (agent client config HCL)\ncheck {\n  type = \"script\"\n  command = \"/usr/local/bin/health.sh\"\n  interval = \"10s\"\n  timeout = \"2s\"\n}\n// after\ncheck {\n  type     = \"http\"\n  path     = \"/v1/agent/health\"\n  interval = \"10s\"\n  timeout  = \"2s\"\n}","handlingStrategy":"validation","validationCode":"// Before writing agent service config, assert check types\nfor _, c := range service.Checks {\n  if c.Type == structs.ServiceCheckScript {\n    return fmt.Errorf(\"agent service %q cannot use script checks; use http/tcp\", service.Name)\n  }\n}","typeGuard":null,"tryCatchPattern":"// if registering programmatically\nif err := client.RegisterAgentWorkload(w); err != nil {\n  if strings.Contains(err.Error(), \"do not support scripts\") {\n    // strip script checks and retry with http/tcp fallback\n  }\n}","preventionTips":["Only use script checks in task-level service blocks, never agent config","Add a config linter that rejects type=\"script\" in agent/client service stanzas","Prefer http checks against the Nomad agent's own /v1/agent/health endpoint","Review Nomad version release notes for agent check type support"],"tags":["consul","nomad","service-registration","config-validation"],"backgroundTag":"unsupported-check-type","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"}