alibaba/ARouter · error · NullPointerException

TimeUnit must not be null.

Error message

TimeUnit must not be null.

What it means

InterceptorInitState.await(timeout, unit) converts the timeout to nanoseconds using the TimeUnit, so a null unit cannot be handled. It throws NullPointerException immediately to fail fast instead of dying inside unit.toNanos().

Source

Thrown at arouter-api/src/main/java/com/alibaba/android/arouter/core/InterceptorInitState.java:75

            lock.notifyAll();
        }
    }

    void fail(Throwable cause) {
        if (cause == null) {
            throw new IllegalArgumentException("Interceptor initialization failure must have a cause.");
        }

        synchronized (lock) {
            status = Status.FAILED;
            failure = cause;
            lock.notifyAll();
        }
    }

    Result await(long timeout, TimeUnit unit) throws InterruptedException {
        if (unit == null) {
            throw new NullPointerException("TimeUnit must not be null.");
        }

        long timeoutNanos = unit.toNanos(timeout);
        long startNanos = System.nanoTime();

        synchronized (lock) {
            while (status != Status.SUCCEEDED && status != Status.FAILED) {
                long elapsedNanos = System.nanoTime() - startNanos;
                long remainingNanos = timeoutNanos - elapsedNanos;
                if (remainingNanos <= 0) {
                    return new Result(Outcome.TIMEOUT, null);
                }

                TimeUnit.NANOSECONDS.timedWait(lock, remainingNanos);
            }

            if (status == Status.FAILED) {
                return new Result(Outcome.FAILURE, failure);

View on GitHub (pinned to 84f451d244)

Solutions

  1. Pass an explicit TimeUnit, e.g. TimeUnit.SECONDS, at every await() call site
  2. If the unit is configurable, default it before calling await
  3. Prefer the MILLIS/SECONDS constant that matches the timeout magnitude to avoid silent unit bugs

Example fix

// before
Result r = initState.await(timeout, null);
// after
Result r = initState.await(timeout, TimeUnit.SECONDS);
Defensive patterns

Strategy: validation

Validate before calling

Objects.requireNonNull(unit, "TimeUnit must not be null");
Result r = initState.await(timeout, unit);

Try / catch

try {
    return initState.await(timeout, TimeUnit.SECONDS);
} catch (InterruptedException e) {
    Thread.currentThread().interrupt();
    return Result.INTERRUPTED;
}

Prevention

When it happens

Trigger: Calling await(timeout, null) — usually because a TimeUnit constant was deleted, refactored to a nullable parameter, or a caller passed a unit variable that was never initialized.

Common situations: Configurable timeout code where the TimeUnit is read from config/defaults and a default was omitted; tests passing null to shortcut the wait.

Related errors


AI-assisted analysis of alibaba/ARouter@84f451d244 (2026-09-06). Data as JSON: /api/errors/56f11663206f99ce. Report an issue: GitHub.