{"record":{"id":"1ee51b97b4390a54","repo":"windmill-labs/windmill","slug":"openprocess-pid-e","errorCode":null,"errorMessage":"OpenProcess({pid}): {e}","messagePattern":"OpenProcess\\((.+?)\\): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/windmill-worker/src/common.rs","lineNumber":903,"sourceCode":"\n        SetInformationJobObject(\n            job,\n            JobObjectExtendedLimitInformation,\n            &info as *const _ as _,\n            std::mem::size_of::<JOBOBJECT_EXTENDED_LIMIT_INFORMATION>() as u32,\n        )\n        .map_err(|e| {\n            let _ = windows::Win32::Foundation::CloseHandle(job);\n            std::io::Error::new(\n                std::io::ErrorKind::Other,\n                format!(\"SetInformationJobObject: {e}\"),\n            )\n        })?;\n\n        let process_handle = OpenProcess(PROCESS_SET_QUOTA | PROCESS_TERMINATE, false, pid)\n            .map_err(|e| {\n                let _ = windows::Win32::Foundation::CloseHandle(job);\n                std::io::Error::new(\n                    std::io::ErrorKind::Other,\n                    format!(\"OpenProcess({pid}): {e}\"),\n                )\n            })?;\n\n        let assign_result = AssignProcessToJobObject(job, process_handle);\n        let _ = windows::Win32::Foundation::CloseHandle(process_handle);\n        assign_result.map_err(|e| {\n            let _ = windows::Win32::Foundation::CloseHandle(job);\n            std::io::Error::new(\n                std::io::ErrorKind::Other,\n                format!(\"AssignProcessToJobObject: {e}\"),\n            )\n        })?;\n\n        Ok(Win32JobHandle(job))\n    }\n}","sourceCodeStart":885,"sourceCodeEnd":921,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/backend/windmill-worker/src/common.rs#L885-L921","documentation":"assign_job_object opens the child process by PID with PROCESS_SET_QUOTA | PROCESS_TERMINATE rights so it can be bound to the job object. If OpenProcess fails (most commonly the process already exited, or access is denied), the job handle is closed and this io::Error is returned including the pid.","triggerScenarios":"assign_job_object called with a pid whose process has already terminated (race between spawn suspension and job assignment) or which the worker account cannot open with the required access rights.","commonSituations":"Child process crashing instantly on startup (bad interpreter, missing DLL) so the pid is dead by assignment time; protected processes; running the worker under a service account lacking rights to the child.","solutions":["Check the pid in the message: if the process exited, look for the child's own startup failure (missing binary/DLL, bad script) — the OpenProcess error is a symptom.","Ensure the worker runs as the same or a more privileged user than the child; grant PROCESS_SET_QUOTA/PROCESS_TERMINATE access.","Reduce time-to-assign or handle spawn failures earlier so dead pids are not passed to assign_job_object.","Retry the job if it was a transient crash."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Pre-check: confirm the child is still alive before assigning it to the job object\nfn process_alive(pid: u32) -> bool {\n    std::process::Command::new(\"tasklist\")\n        .args([\"/FI\", &format!(\"PID eq {pid}\"), \"/NH\"])\n        .output()\n        .map(|o| String::from_utf8_lossy(&o.stdout).contains(&pid.to_string()))\n        .unwrap_or(false)\n}","typeGuard":null,"tryCatchPattern":"match assign_job_object(pid, true) {\n    Err(e) if e.to_string().contains(&format!(\"OpenProcess({pid})\")) => {\n        // child already exited — treat as failed spawn, surface child startup logs\n        Err(std::io::Error::new(\n            std::io::ErrorKind::NotFound,\n            format!(\"child {pid} exited before job assignment: {e}\"),\n        ))\n    }\n    other => other,\n}","preventionTips":["Diagnose why the child exits instantly (missing interpreter, DLL, bad script) — OpenProcess failure is a symptom","Run the worker with an account that can open its children with PROCESS_SET_QUOTA | PROCESS_TERMINATE","Assign the job object as early as possible after spawning the suspended child"],"tags":["windows","win32","process","access-denied"],"backgroundTag":"open-process-access-denied","analyzedSha":"e474e8803ce2ff5c2df09a58dab51d45f5c922ca","analyzedAt":"2026-09-03T12:38:19.024Z","contentChangedAt":"2026-09-03T12:38:19.024Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}