apache/druid · error · ISE
Bad URL: %s
Error message
Bad URL: %s
What it means
HttpPostEmitter's constructor validates config.getRecipientBaseUrl() by constructing a java.net.URL. If the URL is malformed (MalformedURLException), it throws IllegalStateException wrapping the exception with 'Bad URL: <url>'. The emitter cannot deliver events without a syntactically valid recipient URL.
Source
Thrown at processing/src/main/java/org/apache/druid/java/util/emitter/core/HttpPostEmitter.java:176
config.getMaxBatchSize() >= MAX_EVENT_SIZE + batchOverhead,
StringUtils.format(
"maxBatchSize must be greater than MAX_EVENT_SIZE[%,d] + overhead[%,d].",
MAX_EVENT_SIZE,
batchOverhead
)
);
this.config = config;
this.bufferSize = config.getMaxBatchSize();
this.maxBufferWatermark = bufferSize - batchingStrategy.batchEndLength();
// Chosen so that if event size < largeEventThreshold, at least 2 events could fit the standard buffer.
this.largeEventThreshold = (bufferSize - batchOverhead - batchingStrategy.separatorLength()) / 2;
this.client = client;
this.jsonMapper = jsonMapper;
try {
this.url = new URL(config.getRecipientBaseUrl()).toString();
}
catch (MalformedURLException e) {
throw new ISE(e, "Bad URL: %s", config.getRecipientBaseUrl());
}
emittingThread = new EmittingThread(config);
long firstBatchNumber = 1;
concurrentBatch.set(new Batch(this, acquireBuffer(), firstBatchNumber));
// lastBatchFillTimeMillis must not be 0, minHttpTimeoutMillis could be.
lastBatchFillTimeMillis = Math.max(config.minHttpTimeoutMillis, 1);
}
@Override
@LifecycleStart
public void start()
{
synchronized (startLock) {
if (!running) {
if (startLatch.getCount() == 0) {
throw new IllegalStateException("Already started.");
}
running = true;View on GitHub (pinned to 9b90983fd2)
Solutions
- Fix the recipientBaseUrl in config to a full absolute URL including scheme, e.g. http://host:8080/druid/metrics
- Validate the URL with new URL(value) or URI.create(value) before passing it into config
- Check for unresolved environment placeholders or stray whitespace in the property value
Example fix
// before String url = "metrics-host:8080/druid/metrics"; // throws Bad URL // after String url = "http://metrics-host:8080/druid/metrics";
Defensive patterns
Strategy: validation
Validate before calling
String baseUrl = config.getRecipientBaseUrl();
try {
new java.net.URL(baseUrl);
} catch (java.net.MalformedURLException e) {
throw new IllegalArgumentException("recipientBaseUrl must be an absolute URL, got: " + baseUrl);
} Type guard
boolean isValidUrl(String s) {
if (s == null) return false;
try { new java.net.URL(s); return true; } catch (java.net.MalformedURLException e) { return false; }
} Try / catch
try {
Emitter e = new HttpPostEmitter(config, mapper);
} catch (IllegalStateException ex) {
log.error(ex, "Check org.apache.druid.java.util.emitter.http.url value");
throw ex;
} Prevention
- Always include the scheme (http:// or https://) in recipientBaseUrl
- Check for unresolved ${PLACEHOLDER} templates or stray whitespace in config
- Pre-validate with new URL(value) before constructing the emitter
- Avoid hostnames with characters illegal in URLs (e.g. underscores)
When it happens
Trigger: Constructing new HttpPostEmitter(config, jsonMapper) when recipientBaseUrl is not a valid absolute URL (missing scheme, illegal characters, etc.).
Common situations: URL missing the http:// scheme (e.g. 'metrics-host:8080/druid/metrics'); trailing spaces or embedded quotes from config; hostnames with underscores; config templating leaving placeholder text like ${METRICS_URL} unresolved.
Understand the failure class
Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.
Related errors
- %s: Malformed url for DruidNode [%s] and baseUrl [%s]
- Only %s protocols are allowed
- Property[%s] must be set
- Cannot figure out default port for protocol[%s], please set
- Specify only one of %s or %s
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/e348a240a6b1dbc8.
Report an issue: GitHub.