apache/skywalking · error · UnexpectedException

Duration data error, the range between the start time and th

Error message

Duration data error, the range between the start time and the end time can't exceed %d %s

What it means

DurationUtils.buildTimeBuckets() expands a query duration into a list of per-step time buckets. To bound memory, it caps the expansion at MAX_TIME_RANGE buckets; when the do/while loop counter exceeds the cap it throws UnexpectedException with the cap and the step unit (e.g. 'days', 'hours'). This is a hard query-surface limit: the requested range is too wide at the requested precision.

Source

Thrown at oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/DurationUtils.java:158

                case MINUTE:
                    dateTime = dateTime.plusMinutes(1);
                    timeBucket = YYYYMMDDHHMM.print(dateTime);
                    durations.add(new PointOfTime(Long.parseLong(timeBucket)));
                    break;
                case SECOND:
                    dateTime = dateTime.plusSeconds(1);
                    timeBucket = YYYYMMDDHHMMSS.print(dateTime);
                    durations.add(new PointOfTime(Long.parseLong(timeBucket)));
                    break;
            }
            i++;
            if (i > MAX_TIME_RANGE) {
                // days, hours, minutes or seconds
                String stepStr = step.name().toLowerCase() + "s";
                String errorMsg = String.format(
                        "Duration data error, the range between the start time and the end time can't exceed %d %s",
                        MAX_TIME_RANGE, stepStr);
                throw new UnexpectedException(errorMsg);
            }
        }
        while (endTimeBucket != durations.get(durations.size() - 1).getPoint());

        return durations;
    }

    public long startTimeToTimestamp(Step step, String dateStr) {
        switch (step) {
            case DAY:
                return YYYY_MM_DD.parseMillis(dateStr);
            case HOUR:
                return YYYY_MM_DD_HH.parseMillis(dateStr);
            case MINUTE:
                return YYYY_MM_DD_HHMM.parseMillis(dateStr);
            case SECOND:
                return YYYY_MM_DD_HHMMSS.parseMillis(dateStr);
        }

View on GitHub (pinned to 102af09b4a)

Solutions

  1. Narrow the start/end range, or coarsen the step (SECOND → MINUTE → HOUR → DAY) so buckets ≤ MAX_TIME_RANGE.
  2. If a long range at fine granularity is genuinely needed, split the query into multiple windows each under the cap and stitch client-side.
  3. For dashboards, prefer aggregated (OAL-rolled-up) metrics with DAY step instead of raw records at fine steps.

Example fix

# GraphQL query — before
queryDuration: {step: SECOND, start: "2026-01-01 0000", end: "2026-03-01 2359"}

# after
queryDuration: {step: HOUR, start: "2026-01-01 0000", end: "2026-03-01 2359"}
Defensive patterns

Strategy: validation

Validate before calling

// Client-side: estimate bucket count before sending
long stepMillis = step == Step.SECOND ? 1000L : step == Step.MINUTE ? 60_000L : step == Step.HOUR ? 3_600_000L : 86_400_000L;
long buckets = (endTs - startTs) / stepMillis;
if (buckets > MAX_TIME_RANGE) {
    throw new IllegalArgumentException("range too wide for step; coarsen step or split query");
}

Try / catch

try { durations = DurationUtils.INSTANCE.getAllDuration(step, start, end); } catch (UnexpectedException e) { if (e.getMessage().contains("can't exceed")) { /* auto-coarsen step and retry once, or split window */ } else throw e; }

Prevention

When it happens

Trigger: A GraphQL/query API call whose Duration step+start+end expands to more than MAX_TIME_RANGE buckets of that step — e.g. a multi-year range with Step.SECOND, or months with Step.MINUTE; detected after incrementally appending PointOfTime entries until i > MAX_TIME_RANGE before reaching endTimeBucket.

Common situations: UI dashboards or scripts requesting raw second/minute granularity over long windows; defaulting Step to the finest unit while letting users pick wide date ranges; migrating a query from DAY step to MINUTE without shrinking the range.

Related errors


AI-assisted analysis of apache/skywalking@102af09b4a (2026-08-14). Data as JSON: /api/errors/c948299e319bad91. Report an issue: GitHub.