0X000003E4

ERROR_IO_INCOMPLETE (0x3E4): Overlapped I/O Not Signaled

ERROR_IO_INCOMPLETE means a program checked an overlapped I/O operation before it finished. Here's what actually causes it and how to fix it.

ERROR_IO_INCOMPLETE (0x000003E4, decimal 1004) isn't a crash. It's Windows telling you: "You asked me about that overlapped I/O operation, but it hasn't finished yet." That's it. The operation might still complete successfully a millisecond later. The problem is that the calling code treated a pending result as a failure.

You'll see this in Event Viewer, in Windows application logs from backup software, in SAN/NAS clients, in database engines (SQL Server, MySQL on Windows), and any app that uses overlapped reads/writes on files or named pipes. If you're a sysadmin and a backup job starts throwing 0x3E4, don't panic about disk failure. The culprit is almost always one of three things.

Cause 1: App polls overlapped I/O without waiting — the most common case

Overlapped I/O is asynchronous by design. Call ReadFile or WriteFile with an OVERLAPPED structure, and Windows returns immediately with ERROR_IO_PENDING (997). You then have to wait — either with WaitForSingleObject on the event handle in the OVERLAPPED struct, or with an I/O completion port. Only then do you call GetOverlappedResult.

If a developer skips the wait and calls GetOverlappedResult too early, Windows returns ERROR_IO_INCOMPLETE. The operation is fine. The code is wrong.

Classic real-world trigger: a third-party backup agent targeting a network share. The share is on a slow link (VPN, WAN, or a busy NAS), and the agent's polling interval is 100ms. On fast local disk, the read finishes in 20ms and everything looks fine. Put that same agent on a 40ms-latency link and suddenly every read returns 0x3E4. The agent logs an error, the backup fails, and someone files a ticket about "corrupt storage."

If it's your code, the fix is to actually wait:

OVERLAPPED ov = {0};
ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

BOOL ok = ReadFile(hFile, buf, len, NULL, &ov);
if (!ok) {
    DWORD err = GetLastError();
    if (err == ERROR_IO_PENDING) {
        // THIS is the part people skip
        WaitForSingleObject(ov.hEvent, INFINITE);
    } else {
        // real error
    }
}

DWORD bytes = 0;
if (!GetOverlappedResult(hFile, &ov, &bytes, FALSE)) {
    // now you can trust the error code
}

If it's not your code, patch or upgrade the app. Don't waste time on driver updates — they won't help. The bug is in userland.

Cause 2: Network path dropped mid-I/O on a file share or named pipe

Overlapped reads and writes over SMB or named pipes can return 0x3E4 when the underlying transport gets yanked. The handle is still technically valid, but the pending I/O will never signal because the session is dead. Applications that poll see ERROR_IO_INCOMPLETE forever instead of ERROR_NETNAME_DELETED (64) or ERROR_CONNECTION_ABORTED (1236).

You see this on:

  • Wi-Fi laptops that roam between APs mid-write to a mapped drive
  • VPN clients that reconnect while an app has an open handle
  • NAS devices rebooting or failing over to a secondary controller
  • Hyper-V live migration where a VM's vhdx sits on a CSV that briefly drops

The fix, in order:

  1. Close and reopen the handle. There's no recovering a pending I/O whose transport is gone.
  2. Check net use and the SMB session state: Get-SmbSession in PowerShell. If the session is stale, remove the mapped drive and remap.
  3. For VPN users, stop putting file shares over flaky tunnels. Use a sync tool or DFS-R instead of live SMB. This is a design fix, not a registry tweak.
  4. For NAS failover, shorten the SMB timeout so the client fails fast instead of hanging on dead I/O. Set SessTimeout under HKLM\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\Parameters. Default is 45 seconds. Cut it to 15 if you're on a redundant path.

Don't bother disabling SMB signing or tweaking oplocks unless you've confirmed the session is dropping. That stuff rarely helps and usually causes new problems.

Cause 3: Named pipe server stalls or client disappears

Named pipes are overlapped I/O too. If a server process is holding a pipe handle and gets stuck (deadlock, GC pause, thread pool exhaustion), clients polling for completion hit 0x3E4. Same story if the client process exits while a write is still pending — the server's GetOverlappedResult keeps returning ERROR_IO_INCOMPLETE because the completion will never fire.

Common triggers: SQL Server Agent jobs using named pipe connections, Windows services talking to each other via pipes, and any homegrown IPC over \\.\pipe\. I've seen this with older monitoring agents that open a pipe to a service and don't handle the service restarting.

How to confirm: run handle.exe from Sysinternals against the process, look for pipe handles, and check whether the counterpart process is alive. If the client's gone, the pipe handle is orphaned and the server needs to close it and listen again.

For your own pipe code: always register a cleanup path that closes the pipe handle on client disconnect. Use DisconnectNamedPipe then ConnectNamedPipe again. Don't rely on the overlapped event firing — it won't if the other end vanished.

What doesn't cause ERROR_IO_INCOMPLETE

  • Bad RAM. You'd get 0x0000000A or 0xC0000005, not 0x3E4.
  • Failing disks. That's usually 0x0000007B or I/O errors surfaced as 5/23/1117.
  • Missing Visual C++ runtimes. That gives you a totally different failure mode.
  • Antivirus. Occasionally AV filter drivers delay I/O, but they don't return 0x3E4 unless the app was already mishandling async completion.

If someone tells you to run sfc /scannow, humor them, but it won't fix this. ERROR_IO_INCOMPLETE is a programming or session-state problem, not a corrupted-system-file problem.

Quick-reference summary

CauseSymptomFix
Polling overlapped I/O before completionApp logs 0x3E4 but operation eventually succeedsAdd WaitForSingleObject or IOCP before GetOverlappedResult
Network share or SMB session droppedError appears after roam, VPN reconnect, or NAS failoverClose/reopen handle, remap share, shorten SessTimeout
Named pipe server stalled or client gonePipe-based service hangs, error repeatsClose orphaned pipe handle, re-listen; fix server deadlock

Bottom line: 0x3E4 is almost never a hardware problem. It's a caller asking "are we there yet" before the car left the driveway, or a session that quietly died. Find out which one you're dealing with and the fix is usually a code change or a reconnect — not a rebuild.

Related Errors in Windows Errors
0X00000229 Fix 0x00000229: Too Many Active Profiling Objects 0X00003AB7 Fix ERROR_EVT_MAX_INSERTS_REACHED (0x3AB7) on Windows 0X000021C8 Fix 0X000021C8: Duplicate UPN in Active Directory Forest 0XC00D14B7 Fix NS_E_PLAYLIST_UNSUPPORTED_ENTRY (0XC00D14B7) in Windows Media Player

Was this solution helpful?

EP
Erropedia Team
Tech Support Editors
The Erropedia editorial team researches and documents real-world tech errors from across Windows, Linux, macOS, networking, databases, cloud platforms, and more. Every solution is reviewed for accuracy and updated as software and systems evolve.