Bug #120227 LOAD DATA LOCAL INFILE: missing EOF packet on IOException leaves server thread hanging
Submitted: 7 Apr 15:05 Modified: 13 Apr 23:15
Reporter: robi su Email Updates:
Status: Verified Impact on me:
None 
Category:Connector / J Severity:S3 (Non-critical)
Version:9.6.0 OS:Any
Assigned to: Filipe Silva CPU Architecture:Any
Tags: load-data, local-infile, protocol

[7 Apr 15:05] robi su
Description:
When an IOException occurs while reading file data during LOAD DATA LOCAL INFILE (e.g. due to a network interruption or a stream read failure), NativeProtocol.sendFileToServer() throws the exception back to the caller but never sends the empty EOF packet that terminates the file transfer.

The MySQL protocol requires an empty packet to signal end-of-file to the server. Without it, the server thread stays in "executing" state, still waiting for more file data. It will remain blocked until net_read_timeout fires (default 30 seconds).

Meanwhile the JDBC connection is left in a broken state — any follow-up query on the same connection fails with "Got packets out of order" because the server is still processing the previous LOAD DATA command.

The MySQL C client (libmysql.cc, handle_local_infile) correctly sends the empty packet on error before returning.

Tested with Connector/J 9.6.0 against MySQL 9.3.0. The same code exists in 8.0.33 and 9.3.0.

How to repeat:
How to repeat:

Start MySQL with local_infile enabled:
docker run -d --name mysql-test -p 3306:3306 -e MYSQL_ALLOW_EMPTY_PASSWORD=1 mysql:9.3 --local-infile=1

Clone and run the minimal reproduction:
https://github.com/moonsphere/cj-loaddata-ioexception-bug.git (or attach the zip)
cd cj-loaddata-ioexception-bug && mvn compile exec:java

The test uses setLocalInfileInputStream() with a custom InputStream that throws IOException after sending ~100KB. It then checks the server PROCESSLIST and tries a follow-up query.

Output:

Test 1: IOException caught as expected
Test 2: Server thread shows Command=Query, State=executing, Info=LOAD DATA... (still waiting)
Test 3: Follow-up SELECT 1 fails with "Got packets out of order"

Suggested fix:
In NativeProtocol.sendFileToServer(), add an empty EOF packet send in the 

```java
catch(IOException) block before rethrowing:

} catch (IOException ioEx) {
    // Send empty EOF packet so the server can end LOAD DATA cleanly.
    try {
        filePacket.setPosition(0);
        send(filePacket, filePacket.getPosition());
        checkErrorMessage();
    } catch (Exception cleanupEx) {
        // Best-effort; original IOException takes priority.
    }

    // ...existing error message building and rethrow...
}
```

This matches the behavior of the MySQL C client (libmysql.cc handle_local_infile).
[13 Apr 23:15] Filipe Silva
Thank you for your interest in MySQL Connector/J and for taking the time file this report.

Verified as described.