{"record":{"id":"0aad0a4743943949","repo":"apache/druid","slug":"guaranteed-rollup-is-not-supported","errorCode":null,"errorMessage":"Guaranteed rollup is not supported","messagePattern":"Guaranteed rollup is not supported","errorType":"validation","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"indexing-service/src/main/java/org/apache/druid/indexing/common/task/batch/parallel/SinglePhaseSubTask.java","lineNumber":170,"sourceCode":"      // subtaskSpecId can be null only for old task versions.\n      @JsonProperty(\"subtaskSpecId\") @Nullable final String subtaskSpecId,\n      @JsonProperty(\"numAttempts\") final int numAttempts, // zero-based counting\n      @JsonProperty(\"spec\") final ParallelIndexIngestionSpec ingestionSchema,\n      @JsonProperty(\"context\") final Map<String, Object> context\n  )\n  {\n    super(\n        getOrMakeId(id, TYPE, ingestionSchema.getDataSchema().getDataSource()),\n        groupId,\n        taskResource,\n        ingestionSchema.getDataSchema().getDataSource(),\n        context,\n        AbstractTask.computeBatchIngestionMode(ingestionSchema.getIOConfig()),\n        supervisorTaskId\n    );\n\n    if (ingestionSchema.getTuningConfig().isForceGuaranteedRollup()) {\n      throw new UnsupportedOperationException(\"Guaranteed rollup is not supported\");\n    }\n\n    this.subtaskSpecId = subtaskSpecId;\n    this.numAttempts = numAttempts;\n    this.ingestionSchema = ingestionSchema;\n    this.missingIntervalsInOverwriteMode = ingestionSchema.getIOConfig().isAppendToExisting() != true\n                                           && ingestionSchema.getDataSchema()\n                                                             .getGranularitySpec()\n                                                             .inputIntervals()\n                                                             .isEmpty();\n    if (missingIntervalsInOverwriteMode) {\n      addToContext(Tasks.FORCE_TIME_CHUNK_LOCK_KEY, true);\n    }\n    this.ingestionState = IngestionState.NOT_STARTED;\n  }\n\n  @Override\n  public String getType()","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/indexing-service/src/main/java/org/apache/druid/indexing/common/task/batch/parallel/SinglePhaseSubTask.java#L152-L188","documentation":"SinglePhaseSubTask explicitly rejects tuning configs that set forceGuaranteedRollup=true. In the single-phase parallel (native parallel) batch ingestion mode, perfect (guaranteed) rollup is not supported because subtasks cannot coordinate partitioning to guarantee a single final segment per rollup key; only best-effort rollup is possible. The check fires in the subtask constructor, so any subtask spec created with that flag fails immediately.","triggerScenarios":"Creating a SinglePhaseSubTask (used by single-phase parallel index tasks) whose ParallelIndexTuningConfig has forceGuaranteedRollup=true — e.g., copying a tuning config from a two-phase (index_parallel with perfect rollup) setup.","commonSituations":"Users migrating from two-phase parallel ingestion configs that used guaranteed rollup; templated ingestion specs where forceGuaranteedRollup is left enabled; converting compaction/reindexing tasks to single-phase mode without adjusting tuning config.","solutions":["Set forceGuaranteedRollup=false (or remove it) in the tuningConfig of the single-phase parallel ingestion spec","If perfect rollup is mandatory, use the two-phase parallel ingestion mode (with partitioning via HashPartitionSegmentMaster or range partitioning) instead of single-phase","Regenerate the spec via the UI, which omits unsupported tuning options for single-phase tasks"],"exampleFix":"// before\n\"tuningConfig\": { \"type\": \"index_parallel\", \"forceGuaranteedRollup\": true }\n// after\n\"tuningConfig\": { \"type\": \"index_parallel\", \"forceGuaranteedRollup\": false }","handlingStrategy":"validation","validationCode":"// validate spec before submission\nParallelIndexTuningConfig tuning = schema.getTuningConfig();\nif (tuning.isForceGuaranteedRollup()) {\n  throw new IAE(\"forceGuaranteedRollup is unsupported for single-phase parallel ingestion\");\n}","typeGuard":null,"tryCatchPattern":"catch (UnsupportedOperationException e) {\n  if (e.getMessage().equals(\"Guaranteed rollup is not supported\")) {\n    throw new UserConfigException(\"remove forceGuaranteedRollup from tuningConfig or use two-phase mode\");\n  } throw e;\n}","preventionTips":["Set forceGuaranteedRollup=false in all single-phase index_parallel specs","Use spec templates validated against the target ingestion mode","If perfect rollup is required, pick the two-phase parallel mode instead","Lint ingestion JSON against the mode's supported tuning options before submission"],"tags":["ingestion","config","rollup"],"backgroundTag":"unsupported-operation","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"}