{"record":{"id":"0ca2376291865262","repo":"TooTallNate/Java-WebSocket","slug":"can-only-be-started-once","errorCode":null,"errorMessage":" can only be started once.","messagePattern":" can only be started once\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"src/main/java/org/java_websocket/server/WebSocketServer.java","lineNumber":270,"sourceCode":"    for (int i = 0; i < decodercount; i++) {\n      WebSocketWorker ex = new WebSocketWorker();\n      decoders.add(ex);\n    }\n  }\n\n\n  /**\n   * Starts the server selectorthread that binds to the currently set port number and listeners for\n   * WebSocket connection requests. Creates a fixed thread pool with the size {@link\n   * WebSocketServer#AVAILABLE_PROCESSORS}<br> May only be called once.\n   * <p>\n   * Alternatively you can call {@link WebSocketServer#run()} directly.\n   *\n   * @throws IllegalStateException Starting an instance again\n   */\n  public void start() {\n    if (selectorthread != null) {\n      throw new IllegalStateException(getClass().getName() + \" can only be started once.\");\n    }\n    Thread t = new Thread(this);\n    t.setDaemon(isDaemon());\n    t.start();\n  }\n\n  public void stop(int timeout) throws InterruptedException {\n    stop(timeout, \"\");\n  }\n\n  /**\n   * Closes all connected clients sockets, then closes the underlying ServerSocketChannel,\n   * effectively killing the server socket selectorthread, freeing the port the server was bound to\n   * and stops all internal workerthreads.\n   * <p>\n   * If this method is called before the server is started it will never start.\n   *\n   * @param timeout Specifies how many milliseconds the overall close handshaking may take","sourceCodeStart":252,"sourceCodeEnd":288,"githubUrl":"https://github.com/TooTallNate/Java-WebSocket/blob/afeacbf8c0f6f6a761c9d9daed8c813dd3b8ed7d/src/main/java/org/java_websocket/server/WebSocketServer.java#L252-L288","documentation":"WebSocketServer.start() throws IllegalStateException if selectorthread is already set, i.e. the server instance was already started (or run() already executed). A server instance is single-use: once its selector thread exists it cannot be started again; create a new instance to restart.","triggerScenarios":"Calling start() twice on the same WebSocketServer instance; calling start() after run() was invoked directly; test harnesses that start the server in setup and then start it again per test; restart logic that reuses the old object instead of constructing a fresh one.","commonSituations":"Application restart logic (config reload, watchdog) re-calling start(); Spring/CDI re-initialization invoking a @PostConstruct twice; JUnit tests sharing a server field across tests.","solutions":["Guard with a started flag or selectorthread check before calling start(), or catch IllegalStateException and treat it as already-running.","To restart, stop() the server, create a NEW WebSocketServer instance, then call start() on it.","In tests, build the server fresh in @BeforeEach instead of a shared @BeforeAll field."],"exampleFix":"// before\nserver.start(); // second call after earlier start -> IllegalStateException\nserver.start();\n// after\nif (server.selectorthread == null) { // or track your own started flag\n  server.start();\n}\n// or for restarts:\nserver.stop();\nserver = new MyServer(address);\nserver.start();","handlingStrategy":"try-catch","validationCode":"if (server.selectorthread != null) {\n  // already started — skip or restart with a new instance\n}","typeGuard":"static boolean notYetStarted(WebSocketServer s) { return s.selectorthread == null; }","tryCatchPattern":"try {\n  server.start();\n} catch (IllegalStateException e) {\n  log.info(\"Server already started, ignoring duplicate start\");\n}","preventionTips":["Track started state in your own wrapper and make start() idempotent","For restarts always stop() then construct a fresh WebSocketServer instance","In tests, create the server in @BeforeEach rather than sharing one instance across tests"],"tags":["websocket","lifecycle","illegal-state"],"backgroundTag":"invalid-state-transition","analyzedSha":"afeacbf8c0f6f6a761c9d9daed8c813dd3b8ed7d","analyzedAt":"2026-09-09T14:39:47.546Z","contentChangedAt":"2026-09-09T14:39:47.546Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}