apache/druid · error · IllegalArgumentException
Conflicting segment granularities found %s(segmentGranularit
Error message
Conflicting segment granularities found %s(segmentGranularity) and %s(granularitySpec.segmentGranularity). Remove `segmentGranularity` and set the `granularitySpec.segmentGranularity` to the expected granularity
What it means
CompactionTask constructor rejects a spec that sets both the legacy top-level segmentGranularity and the newer granularitySpec.segmentGranularity with different values. Because the two fields would contradict, Druid throws IAE instead of silently picking one.
Source
Thrown at indexing-service/src/main/java/org/apache/druid/indexing/common/task/CompactionTask.java:261
if (!usingConcurrentLocks) {
throw DruidException.forPersona(DruidException.Persona.USER)
.ofCategory(DruidException.Category.INVALID_INPUT)
.build("Minor compaction is only used with REPLACE ingestion mode. Please set ioconfig[%s] to true.", Tasks.USE_CONCURRENT_LOCKS);
}
}
this.dimensionsSpec = dimensionsSpec == null ? dimensions : dimensionsSpec;
this.transformSpec = transformSpec;
this.metricsSpec = metricsSpec;
// Prior to apache/druid#10843 users could specify segmentGranularity using `segmentGranularity`
// Now users should prefer to use `granularitySpec`
// In case users accidentally specify both, and they are conflicting, warn the user instead of proceeding
// by picking one or another.
if (granularitySpec != null
&& segmentGranularity != null
&& !segmentGranularity.equals(granularitySpec.getSegmentGranularity())) {
throw new IAE(StringUtils.format(
"Conflicting segment granularities found %s(segmentGranularity) and %s(granularitySpec.segmentGranularity).\n"
+ "Remove `segmentGranularity` and set the `granularitySpec.segmentGranularity` to the expected granularity",
segmentGranularity,
granularitySpec.getSegmentGranularity()
));
}
if (granularitySpec == null && segmentGranularity != null) {
this.granularitySpec = new ClientCompactionTaskGranularitySpec(segmentGranularity, null, null);
} else {
this.granularitySpec = granularitySpec;
}
this.projections = projections;
this.baseTable = baseTable;
this.tuningConfig = tuningConfig != null ? getTuningConfig(tuningConfig) : null;
this.segmentProvider = new SegmentProvider(dataSource, this.ioConfig.getInputSpec());
// Note: The default compactionRunnerType used here should match the default runner used in CompactSegments#run
// when no runner is detected in the returned compactionTaskQuery.
this.compactionRunner = compactionRunner == nullView on GitHub (pinned to 9b90983fd2)
Solutions
- Remove the legacy top-level segmentGranularity field and keep only granularitySpec.segmentGranularity.
- Make both values identical if both fields must temporarily remain (though removal is preferred).
- Re-generate the compaction config from the current Druid UI/API so only granularitySpec is emitted.
Example fix
// before
"segmentGranularity": "day",
"granularitySpec": { "segmentGranularity": "month" }
// after
"granularitySpec": { "segmentGranularity": "month" } Defensive patterns
Strategy: validation
Validate before calling
if (spec.segmentGranularity != null && spec.granularitySpec != null
&& !spec.segmentGranularity.equals(spec.granularitySpec.getSegmentGranularity())) {
throw new IllegalArgumentException("conflicting segmentGranularity values in compaction spec");
} Try / catch
try { new CompactionTask(...); } catch (IAE e) { if (e.getMessage().contains("Conflicting segment granularities")) { remove legacy field and retry; } else throw e; } Prevention
- Use only granularitySpec.segmentGranularity in new configs.
- Search existing coordinator compaction configs for legacy segmentGranularity before upgrades.
- Emit specs through the current UI/API to avoid legacy fields.
When it happens
Trigger: Building a CompactionTask/CompactionIOConfig JSON with "segmentGranularity":"day" plus a granularitySpec whose segmentGranularity is e.g. "month"; partial migration of old compaction configs to the granularitySpec form after the deprecation.
Common situations: Upgrading Druid versions where compaction specs were hand-edited; coordinator compaction configs edited via UI and API simultaneously; copy-paste between old and new spec examples.
Related errors
- Interval[%s] is empty, must specify a nonempty interval
- Failed to parse metric dimensions and types
- Cannot simultaneously replace and append to existing segment
- Unknown tuningConfig type: [%s], Must be in [%s, %s, %s]
- Index metadata doesn't exist for segment [%s]. Try providing
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/d5404b8af752b4be.
Report an issue: GitHub.