pentaho/pentaho-kettle · error · IOException
Server socket on port " + port + " is already in use by ["…
Error message
Server socket on port " + port + " is already in use by [" + entry.getUser() + "]
What it means
SocketRepository.openServerSocket manages the pool of TCP ports Carte allocates for clustered step data channels. If the port's entry already exists in socketMap and entry.isInUse() is true, it throws IOException("Server socket on port <port> is already in use by [<user>]") — the port is already reserved by another allocation (identified by its user, e.g. a clustered transformation). It is a local port-lease conflict, not necessarily an OS-level bind failure.
Solutions
- Identify the holder from the message ([user] names the owning run) and ensure that transformation releases its port; restart the stuck transformation or Carte.
- Give each cluster schema a distinct, non-overlapping port range (cluster schema 'Sockets buffer size'/port settings).
- Restart the Carte slave to clear the in-memory socketMap if entries are stale after a crash.
- Check with `lsof -i :<port>`/`netstat` whether an OS-level process still holds the port; kill it if orphaned.
- Use a wider port range so concurrent clustered runs don't collide.
Example fix
// before: two cluster schemas share a range clusterSchemaA ports: 40000-40010 clusterSchemaB ports: 40000-40010 // after: disjoint ranges clusterSchemaA ports: 40000-40010 clusterSchemaB ports: 40011-40020
Defensive patterns
Strategy: validation
Validate before calling
// ensure cluster schemas use disjoint port ranges before executing
Set<Interval> ranges = new HashSet<>();
for (ClusterSchema cs : clusterSchemas) {
Interval r = cs.getSocketsPortRange();
if (!ranges.add(r)) throw new IllegalStateException("overlapping port range: " + r);
} Try / catch
try {
int port = socketRepository.allocateServerSocketPort(clusterSchema, user);
} catch (IOException e) {
if (e.getMessage().contains("already in use")) {
log.warn("Port pool exhausted/contended; restarting stale runs or widening range");
// free the holder or widen the range, then retry
} else throw e;
} Prevention
- Assign each cluster schema a unique, non-overlapping port range.
- Always let transformations finish or abort cleanly so ports are released.
- Monitor Carte for orphaned runs after crashes; restart the slave if entries go stale.
When it happens
Trigger: allocateServerSocketPort called for a port that a previous allocation never released (releaseSocket not called after a crashed transformation), or two cluster schemas/transformation runs configured with overlapping port ranges requesting the same port concurrently.
Common situations: Carte restarted improperly or slave transformations killed mid-run leaving entries marked in use; multiple cluster schemas on the same Carte configured with the same port range (e.g. 40000-40020); stale Carte process still holding the port.
Related errors
- Port to close was not found in the Carte socket repository!
- A server socket allocation always has to accompanied by a…
- A server socket allocation always has to accompanied by…
- A server socket allocation always has to accompanied by a…
- A server socket allocation always has to accompanied by a…
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/8dd5cfa887eac633.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/www/SocketRepository.java:110
}
public synchronized ServerSocket openServerSocket( int port, String user ) throws IOException {
SocketRepositoryEntry entry = socketMap.get( port );
if ( entry == null ) {
ServerSocket serverSocket = createServerSocket( port );
entry = new SocketRepositoryEntry( port, serverSocket, true, user );
// Store the entry in the map too!
//
socketMap.put( port, entry );
} else {
// Verify that the socket is not in use...
//
if ( entry.isInUse() ) {
throw new IOException( "Server socket on port " + port + " is already in use by [" + entry.getUser() + "]" );
}
if ( entry.getServerSocket().isClosed() ) {
entry.setServerSocket( createServerSocket( port ) );
}
entry.setInUse( true );
}
return entry.getServerSocket();
}
/**
* We don't actually ever close a server socket, we re-use them as much as possible.
*
* @param port
* @throws IOException
*/
public synchronized void releaseSocket( int port ) throws IOException {
View on GitHub (pinned to f3058517a1)