{"record":{"id":"d5511d3559e38472","repo":"apache/beam","slug":"unexpected-null-result","errorCode":null,"errorMessage":"Unexpected null result.","messagePattern":"Unexpected null result\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"sdks/java/harness/src/main/java/org/apache/beam/fn/harness/state/FnApiTimerBundleTracker.java","lineNumber":227,"sourceCode":"  }\n\n  private static <ArgT, ResultT> Supplier<ResultT> memoizeFunction(\n      Supplier<ArgT> arg, Function<ArgT, ResultT> f) {\n    return new Supplier<ResultT>() {\n      private @Nullable ArgT memoizedArg = null;\n      private @Nullable ResultT memoizedResult = null;\n\n      @Override\n      public ResultT get() {\n        ArgT currentArg = arg.get();\n        if (memoizedArg == null || currentArg != memoizedArg) {\n          this.memoizedArg = currentArg;\n          memoizedResult = f.apply(currentArg);\n        }\n        if (memoizedResult != null) {\n          return memoizedResult;\n        } else {\n          throw new RuntimeException(\"Unexpected null result.\");\n        }\n      }\n    };\n  }\n}\n","sourceCodeStart":209,"sourceCodeEnd":233,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/harness/src/main/java/org/apache/beam/fn/harness/state/FnApiTimerBundleTracker.java#L209-L233","documentation":"This memoizing Supplier wrapper in FnApiTimerBundleTracker caches the result of applying a function and refuses to return a null result, throwing \"Unexpected null result.\" It exists to bridge nullable-checking: a memoized value must be non-null. If the wrapped function ever returns null, this runtime error surfaces instead.","triggerScenarios":"Calling get() on the memoized supplier after f.apply(currentArg) returned null — e.g. a lookup/mapping function used by the timer tracker that fails to find or compute a value.","commonSituations":"Internal harness code path where a mapping (e.g. from timer id to timer value) unexpectedly yields null due to missing state or a bug; rarely hit directly by users.","solutions":["Ensure the wrapped function never returns null (return a sentinel/Optional-compatible value).","Check why the underlying computation produced null — usually missing state for the queried key.","Upgrade Beam; this is an internal invariant and a null here indicates a harness bug.","Capture the stack trace and file an issue with the runner/harness logs."],"exampleFix":"// before\nSupplier<T> memoized = memoize(arg -> map.get(arg)); // may be null\n// after\nSupplier<T> memoized = memoize(arg -> Objects.requireNonNullElse(map.get(arg), DEFAULT));","handlingStrategy":"validation","validationCode":"T result = f.apply(arg);\nif (result == null) {\n  throw new IllegalArgumentException(\"memoized function must not return null\");\n}","typeGuard":"boolean nonNull(Object o) { return o != null; }","tryCatchPattern":"try {\n  T v = memoizedSupplier.get();\n} catch (RuntimeException e) {\n  if (\"Unexpected null result.\".equals(e.getMessage())) {\n    LOG.error(\"Wrapped function returned null — fix the mapping\", e);\n  } else { throw e; }\n}","preventionTips":["Never let memoized functions return null","Use explicit defaults or throw descriptive errors in the wrapped function","Report null-producing paths as harness bugs"],"tags":["null","internal","beam","invariant"],"backgroundTag":"internal-invariant-violation","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}