{"record":{"id":"8f049888ca388976","repo":"apache/shenyu","slug":"timer-task-null","errorCode":null,"errorMessage":"timer task null","messagePattern":"timer task null","errorType":"exception","errorClass":"NullPointerException","httpStatus":null,"severity":"warning","filePath":"shenyu-common/src/main/java/org/apache/shenyu/common/timer/HierarchicalWheelTimer.java","lineNumber":93,"sourceCode":"     * @param tickMs       the tick ms\n     * @param wheelSize    the wheel size\n     * @param startMs      the start ms\n     */\n    public HierarchicalWheelTimer(final String executorName,\n                                  final Long tickMs,\n                                  final Integer wheelSize,\n                                  final Long startMs) {\n        ThreadFactory threadFactory = ShenyuThreadFactory.create(executorName, false);\n        taskExecutor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS,\n                new LinkedBlockingQueue<>(), threadFactory);\n        workerThread = threadFactory.newThread(new Worker(this));\n        timingWheel = new TimingWheel(tickMs, wheelSize, startMs, taskCounter, delayQueue);\n    }\n\n    @Override\n    public void add(final TimerTask timerTask) {\n        if (Objects.isNull(timerTask)) {\n            throw new NullPointerException(\"timer task null\");\n        }\n        this.readLock.lock();\n        try {\n            start();\n            long millis = TimeUnit.NANOSECONDS.toMillis(System.nanoTime());\n            this.addTimerTaskEntry(new TimerTaskList.TimerTaskEntry(this, timerTask, timerTask.getDelayMs() + millis));\n        } finally {\n            this.readLock.unlock();\n        }\n\n    }\n\n    private void addTimerTaskEntry(final TimerTaskList.TimerTaskEntry timerTaskEntry) {\n        if (!timingWheel.add(timerTaskEntry)) {\n            if (!timerTaskEntry.cancelled()) {\n                taskExecutor.submit(() -> timerTaskEntry.getTimerTask().run(timerTaskEntry));\n            }\n        }","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/apache/shenyu/blob/567142e07261b3e615ae8850b30f4421f455cc5d/shenyu-common/src/main/java/org/apache/shenyu/common/timer/HierarchicalWheelTimer.java#L75-L111","documentation":"HierarchicalWheelTimer.add() explicitly throws NullPointerException('timer task null') when passed a null TimerTask. The hierarchical timing wheel cannot schedule an absent task, so the API fails fast before acquiring the read lock and starting the wheel.","triggerScenarios":"Calling add(timerTask) with a null reference — typically a factory/builder returning null, an optional task computed as null, or a map lookup producing null before scheduling.","commonSituations":"Conditional task creation where the null branch is passed through unguarded; refactors where getDelayMs-based task wrappers are built lazily and can be null; tests passing null to probe behavior.","solutions":["Ensure the TimerTask is constructed before calling add(); check why the producing code returned null.","Guard the call site with a null check and skip/log instead of scheduling.","Use Objects.requireNonNull earlier in your own code to surface the origin of the null.","If tasks are conditional, build an Optional<TimerTask> and only add when present."],"exampleFix":"// before\nTimerTask task = maybeBuildTask();\nwheelTimer.add(task); // NPE if null\n// after\nTimerTask task = maybeBuildTask();\nif (task != null) {\n    wheelTimer.add(task);\n}","handlingStrategy":"type-guard","validationCode":"if (task == null) {\n    LOG.warn(\"skipping null timer task\");\n    return;\n}","typeGuard":"void safeAdd(HierarchicalWheelTimer t, TimerTask task) {\n    if (t != null && task != null) {\n        t.add(task);\n    }\n}","tryCatchPattern":"try {\n    wheelTimer.add(task);\n} catch (NullPointerException e) {\n    LOG.error(\"Attempted to schedule null timer task\", e);\n}","preventionTips":["Make task factories return Optional<TimerTask> or non-null defaults instead of null.","Call Objects.requireNonNull at task construction to fail near the source.","Review scheduling call sites after refactors for null-producing lookups."],"tags":["null","timer","scheduling"],"backgroundTag":"null-argument","analyzedSha":"567142e07261b3e615ae8850b30f4421f455cc5d","analyzedAt":"2026-09-12T10:08:21.293Z","contentChangedAt":"2026-09-12T10:08:21.293Z","schemaVersion":2},"datasetVersion":"2026-09-19T12:17:13.211Z"}