{"record":{"id":"42a214bc5ff14a02","repo":"apache/druid","slug":"forceguaranteedrollup-is-incompatible-with-partiti-42a214","errorCode":null,"errorMessage":"forceGuaranteedRollup is incompatible with partitionsSpec: %s","messagePattern":"forceGuaranteedRollup is incompatible with partitionsSpec: (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"indexing-service/src/main/java/org/apache/druid/indexing/common/task/batch/parallel/PerfectRollupWorkerTask.java","lineNumber":75,"sourceCode":"\n    Preconditions.checkArgument(\n        tuningConfig.isForceGuaranteedRollup(),\n        \"forceGuaranteedRollup must be set\"\n    );\n\n    checkPartitionsSpec(tuningConfig.getGivenOrDefaultPartitionsSpec());\n\n    this.granularitySpec = dataSchema.getGranularitySpec();\n    this.dataSchema = dataSchema;\n    this.tuningConfig = tuningConfig;\n  }\n\n  private static void checkPartitionsSpec(PartitionsSpec partitionsSpec)\n  {\n    if (!partitionsSpec.isForceGuaranteedRollupCompatible()) {\n      String incompatibiltyMsg = partitionsSpec.getForceGuaranteedRollupIncompatiblityReason();\n      String msg = \"forceGuaranteedRollup is incompatible with partitionsSpec: \" + incompatibiltyMsg;\n      throw new IllegalArgumentException(msg);\n    }\n  }\n\n  @Override\n  public final boolean requireLockExistingSegments()\n  {\n    return true;\n  }\n\n  @Override\n  public final List<DataSegment> findSegmentsToLock(TaskActionClient taskActionClient, List<Interval> intervals)\n  {\n    throw new UnsupportedOperationException(\"This task locks by timeChunk instead of segment\");\n  }\n\n  @Override\n  public final boolean isPerfectRollup()\n  {","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/indexing-service/src/main/java/org/apache/druid/indexing/common/task/batch/parallel/PerfectRollupWorkerTask.java#L57-L93","documentation":"PerfectRollupWorkerTask requires forceGuaranteedRollup (perfect rollup), which is only compatible with partitioning strategies that produce a fixed, complete partition layout. checkPartitionsSpec() throws IllegalArgumentException when the supplied PartitionsSpec reports itself incompatible, including the spec's own incompatibility reason in the message.","triggerScenarios":"Creating a PerfectRollupWorkerTask (used by perfect-rollup compaction/ingestion) with a partitionsSpec such as dynamic or hashed dimension-based partitioning that cannot guarantee perfect rollup.","commonSituations":"Using a compaction/ingestion config with forceGuaranteedRollup=true but leaving a dynamic partitionsSpec; copying tuning configs from a non-rollup job; Druid version changes where a partitionsSpec's rollup compatibility changed.","solutions":["Set partitionsSpec to a rollup-compatible type (e.g. single-dim/partitioned 'hashed' with numShards or 'range' with resolved boundaries) as required for perfect rollup.","Disable forceGuaranteedRollup if you don't actually need perfect rollup and use the appropriate worker task.","Read the incompatibility reason embedded in the message to see exactly which property of the spec conflicts."],"exampleFix":"// before\n\"partitionsSpec\": { \"type\": \"dynamic\", \"maxTotalRows\": 1000000 },\n\"forceGuaranteedRollup\": true\n// after\n\"partitionsSpec\": { \"type\": \"hashed\", \"numShards\": 4 },\n\"forceGuaranteedRollup\": true","handlingStrategy":"validation","validationCode":"// before creating the task\nif (forceGuaranteedRollup && !partitionsSpec.isForceGuaranteedRollupCompatible()) {\n  throw new IllegalArgumentException(\n    \"forceGuaranteedRollup incompatible: \" + partitionsSpec.getForceGuaranteedRollupIncompatiblityReason());\n}","typeGuard":null,"tryCatchPattern":"try { new PerfectRollupWorkerTask(...); } catch (IllegalArgumentException e) { if (e.getMessage().startsWith(\"forceGuaranteedRollup is incompatible\")) { /* switch partitionsSpec to hashed/range with fixed layout */ } else { throw e; } }","preventionTips":["When forceGuaranteedRollup=true, always use a fixed partition layout (hashed numShards or range with boundaries).","Don't copy tuning configs from dynamic-partitioned jobs into perfect-rollup jobs.","Read the spec's own incompatibility reason in the error message."],"tags":["druid","rollup","partitioning","config-validation"],"backgroundTag":"incompatible-configuration-value","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}