{"record":{"id":"a307c50ed392b911","repo":"apache/druid","slug":"granularityspec-s-intervals-cannot-be-empty-when-u","errorCode":null,"errorMessage":"GranularitySpec's intervals cannot be empty when using replace.","messagePattern":"GranularitySpec's intervals cannot be empty when using replace\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"indexing-service/src/main/java/org/apache/druid/indexing/common/task/batch/parallel/ParallelIndexSupervisorTask.java","lineNumber":257,"sourceCode":"      Map<String, Object> context,\n      boolean isCompactionTask\n  )\n  {\n    super(\n        getOrMakeId(id, TYPE, ingestionSchema.getDataSchema().getDataSource()),\n        groupId,\n        taskResource,\n        ingestionSchema.getDataSchema().getDataSource(),\n        context,\n        ingestionSchema.getTuningConfig().getMaxAllowedLockCount(),\n        computeBatchIngestionMode(ingestionSchema.getIOConfig())\n    );\n\n    this.ingestionSchema = ingestionSchema;\n    this.baseSubtaskSpecName = baseSubtaskSpecName == null ? getId() : baseSubtaskSpecName;\n    if (getIngestionMode() == IngestionMode.REPLACE &&\n        ingestionSchema.getDataSchema().getGranularitySpec().inputIntervals().isEmpty()) {\n      throw new ISE(\"GranularitySpec's intervals cannot be empty when using replace.\");\n    }\n\n    if (isGuaranteedRollup(getIngestionMode(), ingestionSchema.getTuningConfig())) {\n      checkPartitionsSpecForForceGuaranteedRollup(ingestionSchema.getTuningConfig().getGivenOrDefaultPartitionsSpec());\n    }\n\n    this.baseInputSource = ingestionSchema.getIOConfig().getNonNullInputSource();\n    this.missingIntervalsInOverwriteMode = (getIngestionMode()\n                                            != IngestionMode.APPEND)\n                                           && ingestionSchema.getDataSchema()\n                                                             .getGranularitySpec()\n                                                             .inputIntervals()\n                                                             .isEmpty();\n    if (missingIntervalsInOverwriteMode) {\n      addToContext(Tasks.FORCE_TIME_CHUNK_LOCK_KEY, true);\n    }\n\n    awaitSegmentAvailabilityTimeoutMillis = ingestionSchema.getTuningConfig().getAwaitSegmentAvailabilityTimeoutMillis();","sourceCodeStart":239,"sourceCodeEnd":275,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/indexing-service/src/main/java/org/apache/druid/indexing/common/task/batch/parallel/ParallelIndexSupervisorTask.java#L239-L275","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\n\"granularitySpec\": { \"type\": \"uniform\", \"segmentGranularity\": \"day\", \"queryableIntervalsEmpty\": true }\n// after\n\"granularitySpec\": {\n  \"type\": \"uniform\",\n  \"segmentGranularity\": \"day\",\n  \"intervals\": [\"2024-01-01/2024-01-02\"]\n}","handlingStrategy":"validation","validationCode":"if (\"replace\".equals(ingestionMode) && (spec.getDataSchema().getGranularitySpec().inputIntervals() == null\n    || spec.getDataSchema().getGranularitySpec().inputIntervals().isEmpty())) {\n  throw new IllegalArgumentException(\"REPLACE ingestion requires explicit granularitySpec.intervals\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["replace-mode","granularity-spec","validation"],"backgroundTag":"missing-required-config-field","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}