{"record":{"id":"0a4ebfec19ae33a7","repo":"hashicorp/nomad","slug":"could-not-configure-windows-job-object-for-executo","errorCode":null,"errorMessage":"could not configure Windows job object for executor: %w","messagePattern":"could not configure Windows job object for executor: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/shared/executor/executor_windows.go","lineNumber":142,"sourceCode":"\t// note: we don't call CloseHandle on this job handle because we need to\n\t// hold onto it until the executor exits\n\tjob, err := windows.CreateJobObject(nil, nil)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"could not create Windows job object for executor: %w\", err)\n\t}\n\n\tinfo := windows.JOBOBJECT_EXTENDED_LIMIT_INFORMATION{\n\t\tBasicLimitInformation: windows.JOBOBJECT_BASIC_LIMIT_INFORMATION{\n\t\t\tLimitFlags: windows.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE,\n\t\t},\n\t}\n\t_, err = windows.SetInformationJobObject(\n\t\tjob,\n\t\twindows.JobObjectExtendedLimitInformation,\n\t\tuintptr(unsafe.Pointer(&info)),\n\t\tuint32(unsafe.Sizeof(info)))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"could not configure Windows job object for executor: %w\", err)\n\t}\n\n\thandle := windows.CurrentProcess()\n\terr = windows.AssignProcessToJobObject(job, handle)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"could not assign executor to Windows job object: %w\", err)\n\t}\n\n\treturn nil\n}\n\n// Cleanup any still hanging user processes\nfunc (e *UniversalExecutor) killProcessTree(proc *os.Process) error {\n\t// We must first verify if the process is still running.\n\t// (Windows process often lingered around after being reported as killed).\n\thandle, err := syscall.OpenProcess(syscall.PROCESS_TERMINATE|syscall.SYNCHRONIZE|syscall.PROCESS_QUERY_INFORMATION, false, uint32(proc.Pid))\n\tif err != nil {\n\t\treturn os.NewSyscallError(\"OpenProcess\", err)","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/drivers/shared/executor/executor_windows.go#L124-L160","documentation":"After creating the job object, the executor configures it with JOBOBJECT_EXTENDED_LIMIT_INFORMATION (KILL_ON_JOB_CLOSE) via SetInformationJobObject. Failure means the limits could not be applied, so the executor refuses to proceed to avoid launching tasks without kill-on-close protection.","triggerScenarios":"windows.SetInformationJobObject returns an error: invalid handle (job already closed), insufficient privilege, buffer/size mismatch from a Windows API change, or security software interfering.","commonSituations":"Hardened hosts or EDR blocking JobObject configuration; running on unusual Windows builds where the extended limit info struct differs; driver-level security products tampering with the handle.","solutions":["Read the wrapped Windows error code and check the host's System/Application event log for the failing process.","Add AV/EDR exclusions for the Nomad client and executor binaries and retry.","Update Nomad to the latest patch — older versions had struct/size issues on newer Windows builds.","Run the Nomad client under LocalSystem (or an account with the required privileges) and restart.","Apply pending Windows updates and reboot the host."],"exampleFix":"// before\nnomad agent -config=... run as low-privilege user 'svc-nomad' with EDR blocking job config\n// after\n# run client as LocalSystem and exclude binaries from EDR\nsc config Nomad obj= LocalSystem\nSet-MpPreference -ExclusionProcess \"nomad.exe\",\"nomad_executor.exe\"","handlingStrategy":"try-catch","validationCode":"// Go: verify job object configuration works before use\njob, err := windows.CreateJobObject(nil, nil)\nif err != nil {\n    return err\n}\ninfo := windows.JOBOBJECT_EXTENDED_LIMIT_INFORMATION{\n    BasicLimitInformation: windows.JOBOBJECT_BASIC_LIMIT_INFORMATION{\n        LimitFlags: windows.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE,\n    },\n}\nif _, err := windows.SetInformationJobObject(job,\n    windows.JobObjectExtendedLimitInformation,\n    uintptr(unsafe.Pointer(&info)), uint32(unsafe.Sizeof(info))); err != nil {\n    return fmt.Errorf(\"job object config unsupported on this host: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if err := e.setNewProcessGroup(); err != nil {\n    if strings.Contains(err.Error(), \"configure Windows job object\") {\n        // log wrapped Windows code; check struct size/OS build and EDR hooks\n        return fmt.Errorf(\"task launch aborted: %w\", err)\n    }\n    return err\n}","preventionTips":["Keep Nomad up to date for Windows API struct compatibility.","Run on supported Windows builds; apply OS updates.","Exempt nomad.exe and the executor binary from EDR tampering rules.","Run the client as LocalSystem and re-check after each policy change."],"tags":["windows","job-object","process-management","kernel"],"backgroundTag":"job-object-creation-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"}