apache/pulsar · error · IllegalArgumentException
Sink timeout must be a positive number
Error message
Sink timeout must be a positive number
What it means
If the sink config sets a timeoutMs, it must be non-negative (the message says 'positive', the check rejects negative values; null means no timeout). validateAndExtractDetails throws IllegalArgumentException when timeoutMs < 0.
Source
Thrown at pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/SinkConfigUtils.java:455
}
}
if (!isEmpty(sinkConfig.getLogTopic())) {
if (!TopicName.isValid(sinkConfig.getLogTopic())) {
throw new IllegalArgumentException(
String.format("LogTopic topic %s is invalid", sinkConfig.getLogTopic()));
}
}
if (sinkConfig.getParallelism() != null && sinkConfig.getParallelism() <= 0) {
throw new IllegalArgumentException("Sink parallelism must be a positive number");
}
if (sinkConfig.getResources() != null) {
ResourceConfigUtils.validate(sinkConfig.getResources());
}
if (sinkConfig.getTimeoutMs() != null && sinkConfig.getTimeoutMs() < 0) {
throw new IllegalArgumentException("Sink timeout must be a positive number");
}
String sinkClassName = sinkConfig.getClassName();
// if class name in sink config is not set, this should be a built-in sink
// thus we should try to find it class name in the NAR service definition
if (sinkClassName == null) {
ConnectorDefinition connectorDefinition = sinkFunction.getFunctionMetaData(ConnectorDefinition.class);
if (connectorDefinition == null) {
throw new IllegalArgumentException(
"Sink package doesn't contain the META-INF/services/pulsar-io.yaml file.");
}
sinkClassName = connectorDefinition.getSinkClass();
if (sinkClassName == null) {
throw new IllegalArgumentException("Failed to extract sink class from archive");
}
}
// check if sink implements the correct interfacesView on GitHub (pinned to 820761864e)
Solutions
- Set a non-negative timeout in milliseconds, e.g. sinkConfig.setTimeoutMs(30000L).
- To disable the timeout, leave timeoutMs unset (null) instead of -1.
- Fix duration computation that underflows to a negative value.
- Validate timeout >= 0 before submitting.
Example fix
// before sinkConfig.setTimeoutMs(-1L); // intended 'disabled' // after // leave unset to disable: // sinkConfig.setTimeoutMs(null); — or set a real value: sinkConfig.setTimeoutMs(30000L);
Defensive patterns
Strategy: validation
Validate before calling
if (sinkConfig.getTimeoutMs() != null && sinkConfig.getTimeoutMs() < 0) {
throw new IllegalArgumentException("timeoutMs must be >= 0");
} Type guard
static boolean hasValidTimeout(SinkConfig cfg) {
return cfg.getTimeoutMs() == null || cfg.getTimeoutMs() >= 0;
} Try / catch
try {
SinkConfigUtils.validateAndExtractDetails(cfg, sinkPkg, transformPkg, true);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("timeout")) {
log.error("Negative sink timeoutMs: {}", cfg.getTimeoutMs(), e);
}
throw e;
} Prevention
- Treat null as 'no timeout' — don't use -1 as a sentinel.
- Check duration arithmetic for underflow before assigning timeoutMs.
- Validate timeouts read from config files before submission.
- Document timeout semantics (ms, null = disabled) in your tooling.
When it happens
Trigger: SinkConfig.setTimeoutMs(-1) — often from using -1 as a sentinel 'disabled' value in code or config, or an arithmetic underflow when computing the timeout.
Common situations: Users setting '-1' to disable ack timeout based on other systems' conventions; duration parsing producing negative values; copy-pasted config from tools where -1 means infinite.
Understand the failure class
Background: "must be positive", "Invalid value": how libraries reject invalid parameter values (ValueError, ArgumentError, INVALID_PARAMETER_VALUE) — this error's family across 28 libraries.
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Time-out while checking authorization
- Sink tenant cannot be null
- Sink namespace cannot be null
- Sink name cannot be null
- Must specify at least one topic of input via topicToSerdeCla
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/8cf7bd7a923d1d77.
Report an issue: GitHub.