square/retrofit · error · NullPointerException

error == null

Error message

error == null

What it means

`Result.error(Throwable)` at Result.java:26 requires a non-null cause to preserve Result's invariant that exactly one of response/error is set. An error Result must carry a real Throwable so `.error()` callers can rely on it.

Source

Thrown at retrofit-adapters/rxjava3/src/main/java/retrofit2/adapter/rxjava3/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.rxjava3;

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. Pass a concrete non-null Throwable: `Result.error(new IOException("x"))`.
  2. Guard nullable sources: `Result.error(t != null ? t : new IllegalStateException())`.
  3. Let the built-in RxJava3CallAdapter construct Result objects.

Example fix

// before
Result<User> r = Result.error(getErrorOrNull()); // NPE if null

// after
Throwable t = getErrorOrNull();
Result<User> r = Result.error(t != null ? t : new IllegalStateException("no cause"));
Defensive patterns

Strategy: validation

Validate before calling

static <T> Result<T> safeError(Throwable t) {
    if (t == null) throw new IllegalArgumentException("error must not be null");
    return Result.error(t);
}

Try / catch

try {
    Result<User> r = Result.error(maybeNullThrowable);
} catch (NullPointerException e) {
    if (e.getMessage().equals("error == null")) {
        Result<User> r = Result.error(new IllegalStateException("unknown error"));
    } else throw e;
}

Prevention

When it happens

Trigger: Calling `Result.error(null)` in app code, a custom adapter, a converter, or a test fixture.

Common situations: Hand-building Result instances; passing a nullable cause expression from a custom flow.

Related errors


AI-assisted analysis of square/retrofit@d0b112dad0 (2026-08-04). Data as JSON: /data/errors/09f4d3b89e901dad.json. Report an issue: GitHub.