apache/druid · error · IllegalStateException
GranularitySpec's intervals cannot be empty when using…
Error message
GranularitySpec's intervals cannot be empty when using replace.
What it means
Thrown in the ParallelIndexSupervisorTask constructor when the ingestion mode is REPLACE but the GranularitySpec has no explicit input intervals. Replace-mode (MSQ-style compaction/replacement) needs a bounded interval to know which existing segments to replace; implicit interval discovery is not allowed.
Solutions
- Add explicit intervals to the granularitySpec covering the data being replaced.
- If using SQL, include a WHERE clause on __time that yields non-empty intervals for REPLACE.
- Use INSERT (append) mode instead of REPLACE if intervals cannot be determined up front.
Example fix
// before
"granularitySpec": { "type": "uniform", "segmentGranularity": "day", "queryableIntervalsEmpty": true }
// after
"granularitySpec": {
"type": "uniform",
"segmentGranularity": "day",
"intervals": ["2024-01-01/2024-01-02"]
} Defensive patterns
Strategy: validation
Validate before calling
if ("replace".equals(ingestionMode) && (spec.getDataSchema().getGranularitySpec().inputIntervals() == null
|| spec.getDataSchema().getGranularitySpec().inputIntervals().isEmpty())) {
throw new IllegalArgumentException("REPLACE ingestion requires explicit granularitySpec.intervals");
} Prevention
- Always include intervals in granularitySpec for REPLACE tasks
- For SQL REPLACE, constrain __time with a WHERE clause
- Validate task JSON before submission to the overlord
When it happens
Trigger: Submitting a batch parallel task with ingestionMode REPLACE (e.g. via SQL REPLACE or a task JSON) where granularitySpec has no 'intervals' field or relies on 'AUTO' interval discovery.
Common situations: Converting an INSERT-style task spec to REPLACE without adding intervals; generating task JSON programmatically and forgetting intervals; using SQL REPLACE/INSERT OVERWRITE with dynamic intervals disabled.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- A local input source accepts only one of
- A local input source can set parameter
- A local input source requires one parameter of
- A local input source requires one property of
- A table definition must include a table spec.
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/a307c50ed392b911.
Report an issue: GitHub.
Appendix: source
Thrown at indexing-service/src/main/java/org/apache/druid/indexing/common/task/batch/parallel/ParallelIndexSupervisorTask.java:257
Map<String, Object> context,
boolean isCompactionTask
)
{
super(
getOrMakeId(id, TYPE, ingestionSchema.getDataSchema().getDataSource()),
groupId,
taskResource,
ingestionSchema.getDataSchema().getDataSource(),
context,
ingestionSchema.getTuningConfig().getMaxAllowedLockCount(),
computeBatchIngestionMode(ingestionSchema.getIOConfig())
);
this.ingestionSchema = ingestionSchema;
this.baseSubtaskSpecName = baseSubtaskSpecName == null ? getId() : baseSubtaskSpecName;
if (getIngestionMode() == IngestionMode.REPLACE &&
ingestionSchema.getDataSchema().getGranularitySpec().inputIntervals().isEmpty()) {
throw new ISE("GranularitySpec's intervals cannot be empty when using replace.");
}
if (isGuaranteedRollup(getIngestionMode(), ingestionSchema.getTuningConfig())) {
checkPartitionsSpecForForceGuaranteedRollup(ingestionSchema.getTuningConfig().getGivenOrDefaultPartitionsSpec());
}
this.baseInputSource = ingestionSchema.getIOConfig().getNonNullInputSource();
this.missingIntervalsInOverwriteMode = (getIngestionMode()
!= IngestionMode.APPEND)
&& ingestionSchema.getDataSchema()
.getGranularitySpec()
.inputIntervals()
.isEmpty();
if (missingIntervalsInOverwriteMode) {
addToContext(Tasks.FORCE_TIME_CHUNK_LOCK_KEY, true);
}
awaitSegmentAvailabilityTimeoutMillis = ingestionSchema.getTuningConfig().getAwaitSegmentAvailabilityTimeoutMillis();View on GitHub (pinned to 9b90983fd2)