{"record":{"id":"abc73e9b7bbc02e5","repo":"apache/shenyu","slug":"the-task-queue-does-not-have-executor","errorCode":null,"errorMessage":"The task queue does not have executor!","messagePattern":"The task queue does not have executor!","errorType":"exception","errorClass":"RejectedExecutionException","httpStatus":null,"severity":"error","filePath":"shenyu-common/src/main/java/org/apache/shenyu/common/concurrent/TaskQueue.java","lineNumber":47,"sourceCode":"\n    /**\n     * get executor.\n     *\n     * @return the executor\n     */\n    EagerExecutorService getExecutor();\n\n    /**\n     * set the executor.\n     *\n     * @param executor executor\n     */\n    void setExecutor(EagerExecutorService executor);\n\n    @Override\n    default boolean offer(final E e) {\n        if (Objects.isNull(getExecutor())) {\n            throw new RejectedExecutionException(\"The task queue does not have executor!\");\n        }\n\n        int currentPoolThreadSize = getExecutor().getPoolSize();\n        // have free worker. put task into queue to let the worker deal with task.\n        if (getExecutor().getActiveCount() < currentPoolThreadSize) {\n            return doOffer(e);\n        }\n\n        // return false to let executor create new worker.\n        if (currentPoolThreadSize < getExecutor().getMaximumPoolSize()) {\n            return false;\n        }\n\n        // currentPoolThreadSize >= max\n        return doOffer(e);\n    }\n\n    /**","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/apache/shenyu/blob/567142e07261b3e615ae8850b30f4421f455cc5d/shenyu-common/src/main/java/org/apache/shenyu/common/concurrent/TaskQueue.java#L29-L65","documentation":"TaskQueue.offer() requires a reference to its owning EagerExecutorService, set via setExecutor(). If getExecutor() is null (queue used before being wired to an executor, or executor reference cleared), the offer cannot route the task and throws RejectedExecutionException('The task queue does not have executor!').","triggerScenarios":"Offering into a TaskQueue that was constructed manually or deserialized without calling setExecutor(); submitting tasks before the EagerExecutorService finished wiring the queue.","commonSituations":"Creating TaskQueue directly and passing it to a plain ThreadPoolExecutor that never calls setExecutor; tests constructing the queue standalone; initialization-order bugs where produce happens before executor setup.","solutions":["Always create the queue via EagerExecutorService (which calls setExecutor) instead of constructing TaskQueue standalone.","Ensure setExecutor() is invoked before any offer/retryOffer use.","Check for a race where producers start before executor initialization completes.","In tests, inject a mock/stub EagerExecutorService into the queue before offering."],"exampleFix":"// before\nTaskQueue<Runnable> queue = new TaskQueue<>();\nqueue.offer(task); // no executor wired\n// after\nEagerExecutorService exec = new EagerExecutorService(core, max, keepAlive, unit, queue, \"shenyu\", new EagerPolicy<>());\n// executor wires itself into the queue; offer through exec.execute(task)","handlingStrategy":"validation","validationCode":"if (queue.getExecutor() == null) {\n    throw new IllegalStateException(\"TaskQueue must be wired to an EagerExecutorService before use\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    queue.offer(task);\n} catch (RejectedExecutionException e) {\n    LOG.error(\"Queue not initialized: {}\", e.getMessage());\n}","preventionTips":["Construct TaskQueue only through EagerExecutorService so setExecutor happens automatically.","Never offer into a queue created with new TaskQueue() directly.","Enforce initialization order: executor first, producers second."],"tags":["concurrency","queue","initialization"],"backgroundTag":"internal-invariant-violation","analyzedSha":"567142e07261b3e615ae8850b30f4421f455cc5d","analyzedAt":"2026-09-12T10:08:21.293Z","contentChangedAt":"2026-09-12T10:08:21.293Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}