{"record":{"id":"9179bbee25fed6c0","repo":"microg/GmsCore","slug":"timeunit-must-not-be-null","errorCode":null,"errorMessage":"TimeUnit must not be null","messagePattern":"TimeUnit must not be null","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"play-services-tasks/src/main/java/com/google/android/gms/tasks/Tasks.java","lineNumber":51,"sourceCode":"\n/**\n * {@link Task} utility methods.\n */\n@PublicApi\npublic final class Tasks {\n\n    /**\n     * Blocks until the specified Task is complete.\n     *\n     * @return the Task's result\n     * @throws ExecutionException   if the Task fails\n     * @throws InterruptedException if an interrupt occurs while waiting for the Task to complete\n     * @throws TimeoutException     if the specified timeout is reached before the Task completes\n     */\n    public static <TResult> TResult await(Task<TResult> task, long timeout, TimeUnit unit) throws ExecutionException, InterruptedException, TimeoutException {\n        if (task == null) throw new IllegalArgumentException(\"Task must not be null\");\n        if (timeout <= 0) throw new IllegalArgumentException(\"Timeout must be positive\");\n        if (unit == null) throw new IllegalArgumentException(\"TimeUnit must not be null\");\n        if (task.isComplete()) return handleCompletedTask(task);\n        CountDownLatch latch = new CountDownLatch(1);\n        task.addOnCompleteListener(Runnable::run, completedTask -> latch.countDown());\n        if (latch.await(timeout, unit)) {\n            return handleCompletedTask(task);\n        }\n        throw new TimeoutException(\"Timed out waiting for Task\");\n    }\n\n    /**\n     * Blocks until the specified Task is complete.\n     *\n     * @return the Task's result\n     * @throws ExecutionException   if the Task fails\n     * @throws InterruptedException if an interrupt occurs while waiting for the Task to complete\n     */\n    public static <TResult> TResult await(Task<TResult> task) throws ExecutionException, InterruptedException {\n        if (Looper.getMainLooper().getThread() == Thread.currentThread())","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/microg/GmsCore/blob/157c9d86ac46c195a86c2f15ab55c84036223f95/play-services-tasks/src/main/java/com/google/android/gms/tasks/Tasks.java#L33-L69","documentation":"Guard inside the timed overload of Tasks.await(task, timeout, unit). The caller passed a null TimeUnit, so the timeout duration cannot be interpreted (nanoseconds vs seconds are indistinguishable). Rather than silently treating null as some default unit, the method validates its argument and throws to force the caller to name the time unit explicitly.","triggerScenarios":"Calling Tasks.await(task, 5, null) — commonly when the unit comes from an uninitialized field, a config lookup that returned null, or an optional parameter defaulted to null.","commonSituations":"Config-driven timeouts where the unit string failed to map to a TimeUnit; default-parameter mistakes; reflection-built call sites.","solutions":["Always pass a concrete unit such as TimeUnit.SECONDS or TimeUnit.MILLISECONDS","Default null units before the call: unit = unit != null ? unit : TimeUnit.SECONDS","Fix the config/mapping code that produced a null TimeUnit","Validate unit alongside timeout in your own wrapper method"],"exampleFix":"// before\nT r = Tasks.await(task, config.timeout, config.unit); // unit may be null\n// after\nTimeUnit unit = config.unit != null ? config.unit : TimeUnit.SECONDS;\nT r = Tasks.await(task, config.timeout, unit);","handlingStrategy":"validation","validationCode":"if (unit == null) unit = TimeUnit.SECONDS; // or reject explicitly","typeGuard":"boolean hasUnit(TimeUnit u) { return u != null; }","tryCatchPattern":"try {\n    T r = Tasks.await(task, timeout, unit);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"TimeUnit must not be null\")) { /* supply default unit */ }\n}","preventionTips":["Default TimeUnit at config-load time, not at call time","Parse unit strings with TimeUnit.valueOf and reject unknown values early","Keep timeout+unit as a single Duration-like record","Add unit==null assertions in wrapper APIs"],"tags":["tasks","illegal-argument","timeunit","await"],"backgroundTag":"null-argument","analyzedSha":"157c9d86ac46c195a86c2f15ab55c84036223f95","analyzedAt":"2026-09-06T17:27:33.892Z","contentChangedAt":"2026-09-06T17:27:33.892Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}