abhigyanpatwari/GitNexus · error · OSError

SetInformationJobObject failed

Error message

SetInformationJobObject failed

What it means

After creating the job, the harness calls SetInformationJobObject with JobObjectExtendedLimitInformation (class 9) and LimitFlags = 0x00002000 (JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE). If the call returns FALSE, OSError(get_last_error()) is raised and the suspended child is killed and the job closed in the except block.

Source

Thrown at eval/workflow_bench/process_control.py:263

            ctypes.POINTER(wintypes.DWORD),
        ]
        kernel32.QueryInformationJobObject.restype = wintypes.BOOL
        kernel32.CloseHandle.argtypes = [wintypes.HANDLE]
        kernel32.CloseHandle.restype = wintypes.BOOL
        ntdll.NtResumeProcess.argtypes = [wintypes.HANDLE]
        ntdll.NtResumeProcess.restype = wintypes.LONG

        handle = kernel32.CreateJobObjectW(None, None)
        if not handle:
            raise OSError(ctypes.get_last_error(), "CreateJobObjectW failed")
        self._kernel32 = kernel32
        self._handle = handle
        ownership_slot[-1] = (process, self, None)
        try:
            limits = JOBOBJECT_EXTENDED_LIMIT_INFORMATION()
            limits.BasicLimitInformation.LimitFlags = 0x00002000  # KILL_ON_JOB_CLOSE
            if not kernel32.SetInformationJobObject(handle, 9, ctypes.byref(limits), ctypes.sizeof(limits)):
                raise OSError(ctypes.get_last_error(), "SetInformationJobObject failed")
            process_handle = wintypes.HANDLE(int(process._handle))  # type: ignore[attr-defined]
            if not kernel32.AssignProcessToJobObject(handle, process_handle):
                raise OSError(ctypes.get_last_error(), "AssignProcessToJobObject failed")
            status = int(ntdll.NtResumeProcess(process_handle))
            if status != 0:
                raise OSError(status, "NtResumeProcess failed")
        except BaseException:
            # The child is still suspended when assignment fails. Kill it
            # before releasing any handle; never retry with job breakaway.
            process.kill()
            process.wait()
            self.close()
            raise

    def terminate(self) -> None:
        import ctypes

        if self._handle and not self._kernel32.TerminateJobObject(self._handle, 1):

View on GitHub (pinned to d540b00184)

Solutions

  1. Read the captured errno (ctypes.get_last_error() at raise time, stored on OSError.errno) — ERROR_INVALID_PARAMETER (87) suggests struct/size mismatch.
  2. Update to a modern supported Windows build (the harness assumes Vista SP1+ extended limits).
  3. Disable AV/EDR hooks on kernel32 and retry.
  4. Run on Linux to bypass the Windows-job codepath entirely.
Defensive patterns

Strategy: try-catch

Validate before calling

import sys, platform
if sys.platform == 'win32':
    # SetInformationJobObject with JobObjectExtendedLimitInformation needs Vista SP1+.
    ver = platform.win32_ver()[0]
    if ver in ('XP', '2003Server', 'Vista'):
        log.warning('this Windows build may not support extended job limits')

Try / catch

try:
    run_managed(cmd, timeout=60)
except OSError as exc:
    if sys.platform == 'win32' and 'SetInformationJobObject' in str(exc):
        log.error('job limit configuration failed (winerror=%s); update Windows or run on Linux', exc.winerror)
    raise

Prevention

When it happens

Trigger: On Windows when SetInformationJobObject fails — most often because the JOBOBJECT_EXTENDED_LIMIT_INFORMATION struct layout/size is wrong for the running Windows version, or the handle became invalid due to a race. The except clause kills process and closes the job before re-raising.

Common situations: Running on an old Windows version (pre-Vista SP1) that does not support extended limits; alignment / size mismatch from a Python/ctypes version change; security software that intercepts and fails the call.

Related errors


AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12). Data as JSON: /api/errors/d585003abcd99a61. Report an issue: GitHub.