apache/pulsar · error · IllegalArgumentException
expiry time cannot be empty
Error message
expiry time cannot be empty
What it means
RelativeTimeUtil.parseRelativeTimeInSeconds(relativeTime) converts strings like '1000s', '2h', '3d' into seconds. An empty input string cannot denote any time, so it immediately throws IllegalArgumentException('expiry time cannot be empty'). It is a fail-fast input validation error thrown before any parsing.
Source
Thrown at pulsar-common/src/main/java/org/apache/pulsar/common/util/RelativeTimeUtil.java:33
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.pulsar.common.util;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.concurrent.TimeUnit;
import lombok.experimental.UtilityClass;
/**
* Parser for relative time.
*/
@UtilityClass
public class RelativeTimeUtil {
public static long parseRelativeTimeInSeconds(String relativeTime) {
if (relativeTime.isEmpty()) {
throw new IllegalArgumentException("expiry time cannot be empty");
}
int lastIndex = relativeTime.length() - 1;
char lastChar = relativeTime.charAt(lastIndex);
final char timeUnit;
if (!Character.isAlphabetic(lastChar)) {
// No unit specified, assume seconds
timeUnit = 's';
lastIndex = relativeTime.length();
} else {
timeUnit = Character.toLowerCase(lastChar);
}
long duration = Long.parseLong(relativeTime.substring(0, lastIndex));
switch (timeUnit) {
case 's':View on GitHub (pinned to 820761864e)
Solutions
- Set the configuration value to a valid relative time like '3600s', '24h', or '7d'.
- Remove/comment out the empty property so Pulsar applies its default instead of an empty string.
- Guard with a default before parsing, e.g. StringUtils.isBlank(value) ? fallback : parseRelativeTimeInSeconds(value).
- Use a supported unit suffix (s/m/h/d/w) — note the empty check happens first, then unit validation.
Example fix
// before
String cfg = config.get("expiry"); // ""
long secs = RelativeTimeUtil.parseRelativeTimeInSeconds(cfg);
// after
String cfg = config.get("expiry");
long secs = (cfg == null || cfg.isEmpty()) ? defaultSeconds : RelativeTimeUtil.parseRelativeTimeInSeconds(cfg); Defensive patterns
Strategy: validation
Validate before calling
static long safeParse(String cfg, long defaultSeconds) {
if (cfg == null || cfg.isEmpty()) return defaultSeconds;
return RelativeTimeUtil.parseRelativeTimeInSeconds(cfg);
} Type guard
static boolean isValidRelativeTime(String s) {
if (s == null || s.isEmpty()) return false;
char u = s.charAt(s.length() - 1);
return "smhdw".indexOf(u) >= 0 && s.substring(0, s.length() - 1).chars().allMatch(Character::isDigit);
} Try / catch
try { return RelativeTimeUtil.parseRelativeTimeInSeconds(relativeTime); }
catch (IllegalArgumentException e) {
if (relativeTime == null || relativeTime.isEmpty())
throw new IllegalStateException("Configured expiry time is empty; set e.g. '3600s' or remove the property to use the default", e);
throw e;
} Prevention
- Never leave time-related config keys present but blank; remove them to use defaults
- Validate configuration at startup with a fail-fast dump of all time-typed values
- Use environment variable fallbacks: ${ENV:-default}
- Prefer explicit unit suffixes (1000s, 2h, 3d) in all configs
When it happens
Trigger: Calling RelativeTimeUtil.parseRelativeTimeInSeconds("") — typically from a broker configuration value (e.g. ttl or expiry-style settings) that was left blank.
Common situations: broker.conf / client config key present but with an empty value; environment variable expansion yielding an empty string; CLI flag supplied without a value; YAML property defined with no value.
Understand the failure class
Background: "invalid duration" / "failed to parse duration": why your timeout, interval, or TTL string is rejected and which formats each library accepts — this error's family across 32 libraries.
Related errors
- Timeout during delete operation
- Timeout during close operation
- Timeout during open-cursor operation
- Timeout during delete-cursors operation
- Timeout during managed ledger terminate
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/9272df6d5bcb3e33.
Report an issue: GitHub.