ERROR_ALREADY_WIN32 (0X000002CF) — What It Means and How to Fix It
This error means a custom error code you're trying to assign is already taken by a built-in Win32 API error. Happens when writing low-level code or DLLs.
When This Error Shows Up
You'll see ERROR_ALREADY_WIN32 (0X000002CF, decimal 719) when writing a Windows driver, a DLL that calls SetLastError(), or any low-level code that defines custom error codes. The real trigger: you tried to register or assign an error code number that Microsoft already uses for a built-in Win32 API error. For example, if you set error code 2 (which is ERROR_FILE_NOT_FOUND), the system says no — that slot's taken. This error comes back from functions like RtlNtStatusToDosError() or internal error-mapping routines in the kernel.
Root Cause
What's actually happening here is a collision in the Win32 error namespace. Microsoft reserves error codes 0 through 15999 for system use. When you try to map a custom NTSTATUS value or define a new error number that falls inside this range, the error-mapping layer (ntdll.dll or the kernel) rejects it. The reason this check exists is to prevent ambiguity: if two different errors share the same number, code that calls GetLastError() can't tell which one actually occurred. The check isn't arbitrary — it's a safeguard against silent corruption of error information.
The error isn't user-facing 99% of the time. It's a developer error, and it happens at compile time or during driver loading, not while you're running Word. If you're an end user who sees 0X000002CF in a crash log or Event Viewer, it means a driver or system DLL was miscompiled or corrupted.
How to Fix It
Skip any hack that tries to override the reserved range — you can't. The fix is to pick a safe error code number.
- Check the official Win32 error table. Open the Microsoft documentation for System Error Codes. Look for the range 0–15999. Any number there is off-limits for custom use.
- Pick a value above 16000. Microsoft defines custom error ranges starting at 16000 for third-party developers. The safe bet is 16000 + your own offset. For example, 17001. Just pick one that doesn't clash with another vendor's known code.
- Update your source code. Change the constant or macro that defines your custom error number. Example in C:
// Before (collision): #define MY_CUSTOM_ERROR 1234 // 1234 is ERROR_INVALID_LOCK_TYPE // After (safe): #define MY_CUSTOM_ERROR 17001 - Recompile your DLL or driver. Clean and rebuild. The linker won't complain about 0X000002CF anymore because you're not trying to clobber a system error.
- If you're using a .def file or resource-based error mapping, check for any entry that maps an NTSTATUS to a low-numbered DOS error. Change the map target to a value >= 16000.
What to Check If It Still Fails
If the error persists after recompiling:
- Make sure you didn't miss another place that references the old error number. Grep your entire source tree for the decimal number or hex equivalent.
- Check if a third-party library you link against defines its own errors in the reserved range. That library will need to be rebuilt with a safe number too.
- Verify you're not calling
SetLastError()with a reserved value directly. Even if your macro is 17001, a straySetLastError(2)will bypass the compile-time check and silently produce a wrong result. - If you're a user seeing this in Event Viewer: run
sfc /scannowto repair corrupted system files, then reinstall the driver or software that triggered the error. A bad driver or a botched update can cause the system to load a miscompiled binary that hits this error at runtime.
Was this solution helpful?