{"record":{"id":"084972c2463d3345","repo":"shadowsocks/shadowsocks-windows","slug":"unable-to-set-information-error-0","errorCode":null,"errorMessage":"Unable to set information.  Error: {0}","messagePattern":"Unable to set information\\.  Error: (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"shadowsocks-csharp/Util/ProcessManagement/Job.cs","lineNumber":41,"sourceCode":"            var info = new JOBOBJECT_BASIC_LIMIT_INFORMATION\r\n            {\r\n                LimitFlags = 0x2000\r\n            };\r\n\r\n            var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION\r\n            {\r\n                BasicLimitInformation = info\r\n            };\r\n\r\n            try\r\n            {\r\n                int length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));\r\n                extendedInfoPtr = Marshal.AllocHGlobal(length);\r\n                Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false);\r\n\r\n                if (!SetInformationJobObject(handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr,\r\n                        (uint) length))\r\n                    throw new Exception(string.Format(\"Unable to set information.  Error: {0}\",\r\n                        Marshal.GetLastWin32Error()));\r\n            }\r\n            finally\r\n            {\r\n                if (extendedInfoPtr != IntPtr.Zero)\r\n                {\r\n                    Marshal.FreeHGlobal(extendedInfoPtr);\r\n                    extendedInfoPtr = IntPtr.Zero;\r\n                }\r\n            }\r\n        }\r\n\r\n        public bool AddProcess(IntPtr processHandle)\r\n        {\r\n            var succ = AssignProcessToJobObject(handle, processHandle);\r\n\r\n            if (!succ)\r\n            {\r","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/shadowsocks/shadowsocks-windows/blob/891d971682eefcaa2e640258d3b352a3ad3b2233/shadowsocks-csharp/Util/ProcessManagement/Job.cs#L23-L59","documentation":"Exception thrown in the Job constructor when the Win32 SetInformationJobObject call fails. The job object is configured with JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE (0x2000) so child processes die with the parent. The message embeds Marshal.GetLastWin32Error() — the system error code explaining why the limit could not be set.","triggerScenarios":"CreateJobObject returned IntPtr.Zero so SetInformationJobObject operates on a null handle. The process runs on a platform whose kernel32 stubs job-object calls. Insufficient privileges or a security policy denies job creation. The marshalled JOBOBJECT_EXTENDED_LIMIT_INFORMATION size does not match the OS bitness (UIntPtr fields change size), so the length check fails.","commonSituations":"Running on Wine or a non-Windows platform where the call is stubbed. An x86/x64 struct layout mismatch causing ERROR_INVALID_PARAMETER (87). A group policy or sandbox that blocks job creation.","solutions":["Read the numeric Win32 error in the message and look it up (5 = ERROR_ACCESS_DENIED, 6 = ERROR_INVALID_HANDLE, 87 = ERROR_INVALID_PARAMETER, 1001 = ERROR_NOT_SUPPORTED).","Verify the process is running on a real Windows kernel with permission to create jobs.","Confirm the marshalled struct size matches the OS bitness; the UIntPtr/UInt64 fields differ between x86 and x64.","Check that CreateJobObject did not return IntPtr.Zero before calling SetInformationJobObject."],"exampleFix":"// before\nhandle = CreateJobObject(IntPtr.Zero, null);\n// ... SetInformationJobObject(handle, ...) throws if handle is zero\n\n// after\nhandle = CreateJobObject(IntPtr.Zero, null);\nif (handle == IntPtr.Zero)\n    throw new Exception(\"CreateJobObject failed: \" + Marshal.GetLastWin32Error());\n// ... then SetInformationJobObject","handlingStrategy":"try-catch","validationCode":"if (Environment.OSVersion.Platform != PlatformID.Win32NT)\n    throw new PlatformNotSupportedException(\"Job objects require Windows\");\n// verify the job handle before SetInformationJobObject is reached\nif (handle == IntPtr.Zero)\n    throw new Exception(\"CreateJobObject failed: \" + Marshal.GetLastWin32Error());","typeGuard":null,"tryCatchPattern":"try { var job = new Job(); job.AddProcess(proc.Handle); }\ncatch (Exception ex) {\n    // log the Win32 error code; children will not be auto-killed on exit\n    logger.Warn(ex, \"job object unavailable; children may outlive the parent\");\n}","preventionTips":["Check the OS platform before constructing Job.","Decode the Win32 error embedded in the message to find the root cause.","Verify the marshalled struct sizes match the process bitness."],"tags":["windows","process-management","win32","native-interop","job-object"],"backgroundTag":null,"analyzedSha":"891d971682eefcaa2e640258d3b352a3ad3b2233","analyzedAt":"2026-08-13T10:12:34.434Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}