grpc/grpc-java · error · IllegalStateException

No value present.

Error message

No value present.

What it means

StatusOr.getValue() returns the contained value only when no error Status is set. If the StatusOr holds a status instead of a value (hasValue() == false), calling getValue() throws this IllegalStateException. The javadoc explicitly requires checking hasValue() first.

Solutions

  1. Always check hasValue() before calling getValue()
  2. Use getStatus() to inspect and log the error status when hasValue() is false
  3. Propagate the status (e.g. to the stream/stream-trailers) instead of unwrapping
  4. In tests, assert hasValue() before asserting on the value

Example fix

// before
Address addr = statusOr.getValue(); // throws when resolution failed
// after
if (statusOr.hasValue()) {
  Address addr = statusOr.getValue();
} else {
  Status s = statusOr.getStatus(); // handle/log UNAVAILABLE etc.
}
Defensive patterns

Strategy: type-guard

Validate before calling

boolean usable = statusOr != null && statusOr.hasValue();

Type guard

static <T> T getOrThrow(StatusOr<T> or, Supplier<? extends RuntimeException> onAbsent) {
  return or.hasValue() ? or.getValue() : onAbsent.get();
}

Try / catch

try {
  value = statusOr.getValue();
} catch (IllegalStateException e) {
  Status s = statusOr.getStatus(); // inspect/handle error status
}

Prevention

When it happens

Trigger: Calling getValue() on a StatusOr produced from a failed operation — e.g. a failed name resolution (onResult), a lookup that returned an error status — without first checking hasValue(). Callers listed include resolvedAddresses, servers, clusterConfig on error paths.

Common situations: NameResolver results that failed with UNAVAILABLE or similar; xDS cluster config lookup failures; treating a StatusOr as always-successful after refactoring code that previously used exceptions or nullable returns.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08). Data as JSON: /api/errors/70bf6ba72c220949. Report an issue: GitHub.

Appendix: source

Thrown at api/src/main/java/io/grpc/StatusOr.java:59

  /** Construct from a non-Ok status. */
  public static <T> StatusOr<T> fromStatus(Status status) {
    StatusOr<T> result = new StatusOr<T>(checkNotNull(status, "status"), null);
    checkArgument(!status.isOk(), "cannot use OK status: %s", status);
    return result;
  }

  /** Returns whether there is a value. */
  public boolean hasValue() {
    return status == null;
  }

  /**
   * Returns the value if set or throws exception if there is no value set. This method is meant
   * to be called after checking the return value of hasValue() first.
   */
  public T getValue() {
    if (status != null) {
      throw new IllegalStateException("No value present.");
    }
    return value;
  }

  /** Returns the status. If there is a value (which can be null), returns OK. */
  public Status getStatus() {
    return status == null ? Status.OK : status;
  }

  /**
   * Note that StatusOr containing statuses, the equality comparision is delegated to
   * {@link Status#equals} which just does a reference equality check because equality on
   * Statuses is not well defined.
   * Instead, do comparison based on their Code with {@link Status#getCode}.  The description and
   * cause of the Status are unlikely to be stable, and additional fields may be added to Status
   * in the future.
   */
  @Override

View on GitHub (pinned to 64daddc1f3)