lysine-dev/retrofit · error · NullPointerException

error == null

Error message

error == null

What it means

Result.error(Throwable) is the public factory for building an error-valued Result, used by the rxjava2 adapter to deliver network failures inside a reactive stream as data. It explicitly rejects null because a Result must carry a definite error or a definite response — a null error would make the Result semantically empty and break the error()/response() accessor invariants. It throws NullPointerException ('error == null') guarded behind a ConstantConditions suppression so the check is not stripped by static analysis.

Source

Thrown at retrofit-adapters/rxjava2/src/main/java/retrofit2/adapter/rxjava2/Result.java:26

 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package retrofit2.adapter.rxjava2;

import java.io.IOException;
import javax.annotation.Nullable;
import retrofit2.Response;

/** The result of executing an HTTP request. */
public final class Result<T> {
  @SuppressWarnings("ConstantConditions") // Guarding public API nullability.
  public static <T> Result<T> error(Throwable error) {
    if (error == null) throw new NullPointerException("error == null");
    return new Result<>(null, error);
  }

  @SuppressWarnings("ConstantConditions") // Guarding public API nullability.
  public static <T> Result<T> response(Response<T> response) {
    if (response == null) throw new NullPointerException("response == null");
    return new Result<>(response, null);
  }

  private final @Nullable Response<T> response;
  private final @Nullable Throwable error;

  private Result(@Nullable Response<T> response, @Nullable Throwable error) {
    this.response = response;
    this.error = error;
  }

  /**

View on GitHub (pinned to d0b112dad0)

Solutions

  1. Null-check the argument first: `if (cause != null) Result.error(cause) else ...`.
  2. If the call should produce a success, use Result.response(...) instead.
  3. Validate upstream so the throwable reference is never null (e.g. Future.get() can return a null cause on certain ExecutionException shapes).

Example fix

// before
Result<User> r = Result.error(caught);
// after
if (caught == null) throw new IllegalArgumentException("cause must not be null");
Result<User> r = Result.error(caught);
Defensive patterns

Strategy: validation

Validate before calling

Throwable cause = resolveCause();
if (cause == null) throw new IllegalArgumentException("cause required");
Result<User> result = Result.error(cause);

Try / catch

try {
  Result<User> r = Result.error(cause);
} catch (NullPointerException e) {
  // cause was null; supply a fallback or rethrow with context
  throw new IllegalArgumentException("Result.error requires a non-null cause", e);
}

Prevention

When it happens

Trigger: Calling Result.error(null) — most often inside a custom Operator/Transformer that re-wraps a caught Throwable reference that resolved to null, or in test/mocking code. Thrown immediately at the top of Result.error(Throwable).

Common situations: Writing custom RxJava operators that wrap caught exceptions; mock/test setup; defensive catch blocks where the throwable variable is unexpectedly null; Future.get() wrapping where the cause is null.

Related errors


AI-assisted analysis of lysine-dev/retrofit@d0b112dad0 (2026-08-13). Data as JSON: /api/errors/bcc072aadd36d303. Report an issue: GitHub.