square/retrofit · error · NullPointerException
error == null
Error message
error == null
What it means
`Result<T>` is a value object representing the outcome of one HTTP call -- it holds either a Response or an error, never both, never neither. The factory method `Result.error(Throwable)` at Result.java:26 rejects a null throwable to preserve that invariant: an error Result must carry a real cause so downstream code (and `.error()`) can rely on it.
Source
Thrown at retrofit-adapters/rxjava/src/main/java/retrofit2/adapter/rxjava/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.rxjava;
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
- Pass a non-null Throwable, e.g. `Result.error(new IOException("boom"))`.
- If the source can legitimately be null, supply a sentinel/default exception: `Result.error(t != null ? t : new IllegalStateException("unknown"))`.
- Prefer letting the built-in RxJavaCallAdapter construct Result instances rather than building them yourself.
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
// Validate before constructing:
static <T> Result<T> safeError(Throwable t) {
if (t == null) throw new IllegalArgumentException("error must not be null");
return Result.error(t);
} Try / catch
// If the throwable may be null, guard at the call site:
try {
Result<User> r = Result.error(maybeNullThrowable);
} catch (NullPointerException e) {
if (e.getMessage().equals("error == null")) {
// supply a default cause or log and skip
Result<User> r = Result.error(new IllegalStateException("unknown error"));
} else throw e;
} Prevention
- Never pass a nullable expression into Result.error().
- Let the RxJavaCallAdapter build Result objects; do not hand-roll them.
- When writing tests, always supply a concrete exception.
When it happens
Trigger: Calling `Result.error(null)` directly in application code, a custom call adapter, a converter, or a test fixture. The null check fires immediately at Result.java:26.
Common situations: Writing a custom adapter that wraps failures and passing a null cause when a sub-call returned null; building Result instances by hand in tests; or chaining `Result.error(something_that_might_be_null)` without guarding.
Related errors
AI-assisted analysis of square/retrofit@d0b112dad0 (2026-08-04).
Data as JSON: /data/errors/07f7ab75e3045039.json.
Report an issue: GitHub.