microg/GmsCore · error · IllegalArgumentException
maxUpdateDelayMillis must be greater than or equal to 0
Error message
maxUpdateDelayMillis must be greater than or equal to 0
What it means
setMaxUpdateDelayMillis validates that the batching delay is non-negative. This value controls how long a location update may be held back to batch deliveries; a negative delay has no meaning, so the builder throws IllegalArgumentException immediately.
Source
Thrown at play-services-location/src/main/java/com/google/android/gms/location/LocationRequest.java:750
* as high as is reasonable to allow for additional power savings. When the {@link LocationRequest} is built, the maximum
* update delay will be set to the max of the provided maximum update delay and the interval. This normalizes requests
* without batching to have the maximum update delay equal to the interval.
* <p>
* For example, if a request is made with a 2s interval and a 10s maximum update delay, this implies that the device may
* choose to deliver batches of 5 locations every 10s (where each location in a batch represents a point in time ~2s after
* the previous).
* <p>
* Support for batching may vary by device hardware, so simply allowing batching via this parameter does not imply a client
* will receive batched results on all devices.
* <p>
* {@link FusedLocationProviderClient#flushLocations()} may be used to flush locations that have been batched, but not
* delivered yet.
* <p>
* The default value is 0.
*/
@NonNull
public Builder setMaxUpdateDelayMillis(long maxUpdateDelayMillis) {
if (maxUpdateDelayMillis < 0) throw new IllegalArgumentException("maxUpdateDelayMillis must be greater than or equal to 0");
this.maxUpdateDelayMillis = maxUpdateDelayMillis;
return this;
}
/**
* Sets the maximum number of updates delivered to this request. A location request will not receive any locations after the
* maximum number of updates has been reached, and will be removed shortly thereafter. A value of {@link Integer#MAX_VALUE}
* implies an unlimited number of updates.
* <p>
* The default value is {@link Integer#MAX_VALUE}.
*/
@NonNull
public Builder setMaxUpdates(int maxUpdates) {
if (maxUpdates <= 0) throw new IllegalArgumentException("maxUpdates must be greater than 0");
this.maxUpdates = maxUpdates;
return this;
}
View on GitHub (pinned to 157c9d86ac)
Solutions
- Clamp the value before the call: builder.setMaxUpdateDelayMillis(Math.max(0, delayMillis)).
- Validate config/user-supplied delays at the boundary so negatives never reach the builder.
- Confirm argument order in any wrapper method that forwards parameters to setMaxUpdateDelayMillis.
Example fix
// before long delay = maxDelay - extra; // may be negative builder.setMaxUpdateDelayMillis(delay); // after long delay = Math.max(0, maxDelay - extra); builder.setMaxUpdateDelayMillis(delay);
Defensive patterns
Strategy: validation
Validate before calling
public static boolean isValidMaxUpdateDelay(long delayMillis) {
return delayMillis >= 0;
}
long safeDelay = Math.max(0, requestedDelay); Type guard
static boolean isNonNegative(long v) { return v >= 0; } Try / catch
try {
return builder.setMaxUpdateDelayMillis(delay);
} catch (IllegalArgumentException e) {
if (!e.getMessage().contains("maxUpdateDelayMillis")) throw e;
return builder.setMaxUpdateDelayMillis(0); // disable batching on bad input
} Prevention
- Clamp dynamic batching delays: Math.max(0, budget - overrun).
- Validate server/config-driven delay values at deserialization time.
- In wrapper APIs, assert argument order before forwarding longs to the builder.
When it happens
Trigger: Calling builder.setMaxUpdateDelayMillis(-1) or any negative long, often from a computed value like (budget - overrun) or a mis-signed config field.
Common situations: Dynamically shrinking a batching delay faster than the current delay value; server-driven config containing negative delays; parameter-order mix-ups when a helper wraps the builder and forwards arguments in the wrong sequence.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- intervalMillis must be greater than 0
- maxUpdateAgeMillis must be greater than or equal to 0, or IM
- deleteAll was set to true but keys were also provided
- Element in keys cannot be null or empty
- retrieveAll was set to true but other constraint(s) was also
AI-assisted analysis of microg/GmsCore@157c9d86ac (2026-09-06).
Data as JSON: /api/errors/67dbd978e638532f.
Report an issue: GitHub.