{"record":{"id":"8dd5cfa887eac633","repo":"pentaho/pentaho-kettle","slug":"server-socket-on-port-port-is-already-in-use-by-entry","errorCode":null,"errorMessage":"Server socket on port \" + port + \" is already in use by [\" + entry.getUser() + \"]","messagePattern":"Server socket on port \" \\+ port \\+ \" is already in use by \\[\" \\+ entry\\.getUser\\(\\) \\+ \"\\]","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/www/SocketRepository.java","lineNumber":110,"sourceCode":"  }\n\n  public synchronized ServerSocket openServerSocket( int port, String user ) throws IOException {\n\n    SocketRepositoryEntry entry = socketMap.get( port );\n    if ( entry == null ) {\n\n      ServerSocket serverSocket = createServerSocket( port );\n      entry = new SocketRepositoryEntry( port, serverSocket, true, user );\n\n      // Store the entry in the map too!\n      //\n      socketMap.put( port, entry );\n\n    } else {\n      // Verify that the socket is not in use...\n      //\n      if ( entry.isInUse() ) {\n        throw new IOException( \"Server socket on port \" + port + \" is already in use by [\" + entry.getUser() + \"]\" );\n      }\n      if ( entry.getServerSocket().isClosed() ) {\n        entry.setServerSocket( createServerSocket( port ) );\n      }\n      entry.setInUse( true );\n    }\n\n    return entry.getServerSocket();\n  }\n\n  /**\n   * We don't actually ever close a server socket, we re-use them as much as possible.\n   *\n   * @param port\n   * @throws IOException\n   */\n  public synchronized void releaseSocket( int port ) throws IOException {\n","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/www/SocketRepository.java#L92-L128","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: two cluster schemas share a range\nclusterSchemaA ports: 40000-40010\nclusterSchemaB ports: 40000-40010\n\n// after: disjoint ranges\nclusterSchemaA ports: 40000-40010\nclusterSchemaB ports: 40011-40020","handlingStrategy":"validation","validationCode":"// ensure cluster schemas use disjoint port ranges before executing\nSet<Interval> ranges = new HashSet<>();\nfor (ClusterSchema cs : clusterSchemas) {\n  Interval r = cs.getSocketsPortRange();\n  if (!ranges.add(r)) throw new IllegalStateException(\"overlapping port range: \" + r);\n}","typeGuard":null,"tryCatchPattern":"try {\n  int port = socketRepository.allocateServerSocketPort(clusterSchema, user);\n} catch (IOException e) {\n  if (e.getMessage().contains(\"already in use\")) {\n    log.warn(\"Port pool exhausted/contended; restarting stale runs or widening range\");\n    // free the holder or widen the range, then retry\n  } else throw e;\n}","preventionTips":["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."],"tags":["network","port","carte","clustering","socket"],"backgroundTag":"address-already-in-use","analyzedSha":"f3058517a153da500bf4551f46d79b91bf8ec552","analyzedAt":"2026-09-13T14:04:16.340Z","contentChangedAt":"2026-09-13T14:04:16.340Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}