{"record":{"id":"e6a0047635ca3ef3","repo":"perwendel/spark","slug":"this-must-be-done-before-route-mapping-has-begun","errorCode":null,"errorMessage":"This must be done before route mapping has begun","messagePattern":"This must be done before route mapping has begun","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"src/main/java/spark/Service.java","lineNumber":504,"sourceCode":"    /**\n     * Waits for the spark server to be initialized.\n     * If it's already initialized will return immediately\n     */\n    public void awaitInitialization() {\n        if (!initialized) {\n    \t        throw new IllegalStateException(\"Server has not been properly initialized\");\n        }\n\n        try {\n            initLatch.await();\n        } catch (InterruptedException e) {\n            LOG.info(\"Interrupted by another thread\");\n            Thread.currentThread().interrupt();\n        }\n    }\n\n    private void throwBeforeRouteMappingException() {\n        throw new IllegalStateException(\n                \"This must be done before route mapping has begun\");\n    }\n\n    private boolean hasMultipleHandlers() {\n        return webSocketHandlers != null;\n    }\n\n\n    /**\n     * Stops the Spark server and clears all routes.\n     */\n    public synchronized void stop() {\n    \tif (!initialized) {\n    \t\treturn;\n    \t}\n        initiateStop();\n    }\n","sourceCodeStart":486,"sourceCodeEnd":522,"githubUrl":"https://github.com/perwendel/spark/blob/1973e402f5d4c1442ad34a1d38ed0758079f7773/src/main/java/spark/Service.java#L486-L522","documentation":"throwBeforeRouteMappingException is Service's shared helper that raises IllegalStateException('This must be done before route mapping has begun'). Server configuration methods — ipAddress, port(int), threadPool, secure, staticFileLocation, embeddedServerIdentifier — must run before Spark initializes its embedded server, which happens as soon as route mapping begins. Calling them afterwards is a lifecycle-ordering violation, so the server refuses.","triggerScenarios":"Calling any of ipAddress(...), port(...), threadPool(...), secure(...), staticFileLocation(...), or embeddedServerIdentifier(...) after at least one route-mapping call (get/post/put/staticFiles...) has initialized the service.","commonSituations":"Configuration split across classes where routes are registered before settings; conditional config applied late; setting the IP/port in a request handler or framework callback that runs after boot.","solutions":["Move all Spark.port/ipAddress/threadPool/secure/staticFileLocation calls to the very beginning of the bootstrap, before any route registration.","Restructure bootstrap into a single ordered init method: configure server first, then map routes, then init().","In modular apps, split 'server config' and 'route registration' phases with enforced ordering."],"exampleFix":"// before\nSpark.get(\"/hello\", (req, res) -> \"hi\");\nSpark.port(8080); // IllegalStateException\n// after\nSpark.port(8080);\nSpark.get(\"/hello\", (req, res) -> \"hi\");","handlingStrategy":"validation","validationCode":"// enforce ordering in your bootstrap\nconfigureServer(Spark.port(8080));\nmapRoutes();","typeGuard":null,"tryCatchPattern":"try {\n    Spark.staticFileLocation(\"/public\");\n} catch (IllegalStateException e) {\n    throw new IllegalStateException(\"staticFileLocation must be called before route mapping; fix bootstrap order\", e);\n}","preventionTips":["Keep a single ordered bootstrap: config first, routes second, init last.","Never set port/ip/threadPool/staticFiles from request handlers or late callbacks.","Add an integration smoke test that starts the app to catch ordering regressions."],"tags":["java","illegal-state","server-lifecycle"],"backgroundTag":"invalid-state-transition","analyzedSha":"1973e402f5d4c1442ad34a1d38ed0758079f7773","analyzedAt":"2026-09-10T14:38:22.866Z","contentChangedAt":"2026-09-10T14:38:22.866Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}