{"record":{"id":"4d3822421e80500a","repo":"hashicorp/nomad","slug":"jobid-required-for-actions","errorCode":null,"errorMessage":"JobID required for actions","messagePattern":"JobID required for actions","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/job_endpoint.go","lineNumber":1727,"sourceCode":"\tif done, err := j.srv.forward(structs.JobGetActionsRPCMethod, args, args, reply); done {\n\t\treturn err\n\t}\n\tj.srv.MeasureRPCRate(\"job\", structs.RateMetricRead, args)\n\tif authErr != nil {\n\t\treturn structs.ErrPermissionDenied\n\t}\n\tdefer metrics.MeasureSince([]string{\"nomad\", \"job\", \"get_actions\"}, time.Now())\n\n\t// Check for read-job permissions\n\tif aclObj, err := j.srv.ResolveACL(args); err != nil {\n\t\treturn err\n\t} else if !aclObj.AllowNsOp(args.RequestNamespace(), acl.NamespaceCapabilityReadJob) {\n\t\treturn structs.ErrPermissionDenied\n\t}\n\n\t// Validate the arguments\n\tif args.JobID == \"\" {\n\t\treturn fmt.Errorf(\"JobID required for actions\")\n\t}\n\n\t// Grab the job\n\tjob, err := j.srv.fsm.State().JobByID(nil, args.RequestNamespace(), args.JobID)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif job == nil {\n\t\treturn structs.NewErrUnknownJob(args.JobID)\n\t}\n\n\t// Get its task groups' tasks' actions\n\tjobActions := make([]*structs.JobAction, 0)\n\tfor _, tg := range job.TaskGroups {\n\t\tfor _, task := range tg.Tasks {\n\t\t\tfor _, action := range task.Actions {\n\t\t\t\tjobAction := &structs.JobAction{\n\t\t\t\t\tAction:        *action,","sourceCodeStart":1709,"sourceCodeEnd":1745,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/job_endpoint.go#L1709-L1745","documentation":"Job.GetActions was called with an empty JobID. The endpoint validates arguments after ACL checks and requires a job ID to scope the actions query, rejecting the request with 'JobID required for actions'.","triggerScenarios":"GET /v1/job//actions or an ActionsRequest with args.JobID == \"\" (caller has ReadJob ACL but supplies no ID), at nomad/job_endpoint.go:1727.","commonSituations":"Dashboard/UI code navigating to an actions endpoint without a selected job; API wrappers omitting the path parameter; CI scripts with an unset job-name variable.","solutions":["Populate JobID (the request's job field) before calling GetActions.","Ensure the UI/route always carries the job name/id as a path parameter.","Validate non-empty JobID client-side to fail early with a clear message.","Confirm you intended a job-scoped call, not a namespace-wide listing endpoint."],"exampleFix":"// before\nactions, _, err := client.Jobs().GetActions(\"\", nil)\n// after\nif jobID == \"\" { return errors.New(\"GetActions needs a job ID\") }\nactions, _, err := client.Jobs().GetActions(jobID, nil)","handlingStrategy":"validation","validationCode":"if jobID == \"\" {\n    return fmt.Errorf(\"GetActions requires a job ID\")\n}\nactions, _, err := client.Jobs().GetActions(jobID, nil)","typeGuard":"func hasJobID(id string) bool { return id != \"\" }","tryCatchPattern":null,"preventionTips":["Always plumb the job name/id through UI routes into actions requests.","Check for unset CLI flags or env vars before constructing the request.","Add an integration test that asserts non-empty job IDs in action queries."],"tags":["nomad","request-validation","missing-parameter"],"backgroundTag":"missing-required-argument","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"}