{"record":{"id":"1c091daa6a4a4345","repo":"apache/druid","slug":"period-must-not-be-negative-supplied-period","errorCode":null,"errorMessage":"period must not be negative. Supplied period: ","messagePattern":"period must not be negative\\. Supplied period: ","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"server/src/main/java/org/apache/druid/server/compaction/AbstractReindexingRule.java","lineNumber":82,"sourceCode":"\n  /**\n   * Validates that a period represents a non-negative duration (>= 0).\n   * <p>\n   * Zero periods (P0D) are allowed - they indicate rules that should apply immediately to all data.\n   * Negative periods are rejected as they would be nonsensical.\n   * <p>\n   * For periods with precise units (days, hours, minutes, seconds), validates by converting\n   * to a standard duration. For periods with variable-length units (months, years), validates\n   * that no components are negative, since these cannot be converted to a precise duration.\n   *\n   * @param period the period to validate\n   * @throws IllegalArgumentException if the period is negative\n   */\n  private static void validatePeriodIsNonNegative(Period period)\n  {\n    if (hasMonthsOrYears(period)) {\n      if (isPeriodNegative(period)) {\n        throw new IllegalArgumentException(\"period must not be negative. Supplied period: \" + period);\n      }\n    } else {\n      if (period.toStandardDuration().getMillis() < 0) {\n        throw new IllegalArgumentException(\"period must not be negative. Supplied period: \" + period);\n      }\n    }\n  }\n\n  /**\n   * Checks if a period with variable-length components (months/years) has any negative components.\n   * <p>\n   * This is purposely an unscientific check that simply ensures no negative values are present in any component of the period.\n   * It should be \"good enough\" for almost all reasonable use cases.\n   *\n   * @param period the period to check\n   * @return true if any component is negative\n   */\n  private static boolean isPeriodNegative(Period period)","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/server/src/main/java/org/apache/druid/server/compaction/AbstractReindexingRule.java#L64-L100","documentation":"Compaction rules (reindexing rules) that use a Period require a non-negative period to define how far back data is retained/compacted. When the period contains months or years (variable-length components that cannot be converted to a fixed duration), validatePeriodIsNonNegative checks each component and throws this IllegalArgumentException if any part is negative.","triggerScenarios":"Submitting a load/compaction rule JSON with a period containing months or years whose components are negative, e.g. \"period\": \"P-1M\" or \"-PT24H\" combined with month/year fields.","commonSituations":"Typo'd ISO-8601 period strings in rule JSON (a stray leading '-' or '-' inside the period); programmatically built Period objects from signed durations; copy-pasted rules edited by hand in the Druid console.","solutions":["Correct the period string in the rule to a non-negative value, e.g. change \"P-1M\" to \"P1M\".","Re-submit the rule via POST /druid/coordinator/v1/rules with the fixed period.","Validate the Period object before constructing the rule if rules are generated in code."],"exampleFix":"// before\n{\"type\": \"loadByPeriod\", \"period\": \"P-1M\"}\n// after\n{\"type\": \"loadByPeriod\", \"period\": \"P1M\"}","handlingStrategy":"validation","validationCode":"function validatePeriod(p) {\n  if (/[YM]/.test(p) && /-/.test(p.replace(/^P/, ''))) {\n    throw new Error(`period must not be negative: ${p}`);\n  }\n}\nvalidatePeriod(rule.period);","typeGuard":"function isNonNegativePeriodString(p) {\n  return /^P(?!.*-)/.test(p);\n}","tryCatchPattern":"try {\n  coordinator.submitRule(rule);\n} catch (IllegalArgumentException e) {\n  if (e.getMessage().startsWith(\"period must not be negative\")) {\n    log.error(`Fix rule period: ${e.getMessage()}`);\n  } else { throw e; }\n}","preventionTips":["Write ISO-8601 period strings without minus signs; use the format PnYnMnDTnHnMnS.","Lint rule JSON for '-' inside period fields before submitting to the Coordinator."],"tags":["validation","compaction","period","config"],"backgroundTag":"invalid-config-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"}