{"record":{"id":"c948299e319bad91","repo":"apache/skywalking","slug":"duration-data-error-the-range-between-the-start-t","errorCode":null,"errorMessage":"Duration data error, the range between the start time and the end time can't exceed %d %s","messagePattern":"Duration data error, the range between the start time and the end time can't exceed (.+?) (.+?)","errorType":"validation","errorClass":"UnexpectedException","httpStatus":null,"severity":"error","filePath":"oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/DurationUtils.java","lineNumber":158,"sourceCode":"                case MINUTE:\n                    dateTime = dateTime.plusMinutes(1);\n                    timeBucket = YYYYMMDDHHMM.print(dateTime);\n                    durations.add(new PointOfTime(Long.parseLong(timeBucket)));\n                    break;\n                case SECOND:\n                    dateTime = dateTime.plusSeconds(1);\n                    timeBucket = YYYYMMDDHHMMSS.print(dateTime);\n                    durations.add(new PointOfTime(Long.parseLong(timeBucket)));\n                    break;\n            }\n            i++;\n            if (i > MAX_TIME_RANGE) {\n                // days, hours, minutes or seconds\n                String stepStr = step.name().toLowerCase() + \"s\";\n                String errorMsg = String.format(\n                        \"Duration data error, the range between the start time and the end time can't exceed %d %s\",\n                        MAX_TIME_RANGE, stepStr);\n                throw new UnexpectedException(errorMsg);\n            }\n        }\n        while (endTimeBucket != durations.get(durations.size() - 1).getPoint());\n\n        return durations;\n    }\n\n    public long startTimeToTimestamp(Step step, String dateStr) {\n        switch (step) {\n            case DAY:\n                return YYYY_MM_DD.parseMillis(dateStr);\n            case HOUR:\n                return YYYY_MM_DD_HH.parseMillis(dateStr);\n            case MINUTE:\n                return YYYY_MM_DD_HHMM.parseMillis(dateStr);\n            case SECOND:\n                return YYYY_MM_DD_HHMMSS.parseMillis(dateStr);\n        }","sourceCodeStart":140,"sourceCodeEnd":176,"githubUrl":"https://github.com/apache/skywalking/blob/102af09b4a56064e22050dded10e2c52e490d040/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/DurationUtils.java#L140-L176","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Narrow the start/end range, or coarsen the step (SECOND → MINUTE → HOUR → DAY) so buckets ≤ MAX_TIME_RANGE.","If a long range at fine granularity is genuinely needed, split the query into multiple windows each under the cap and stitch client-side.","For dashboards, prefer aggregated (OAL-rolled-up) metrics with DAY step instead of raw records at fine steps."],"exampleFix":"# GraphQL query — before\nqueryDuration: {step: SECOND, start: \"2026-01-01 0000\", end: \"2026-03-01 2359\"}\n\n# after\nqueryDuration: {step: HOUR, start: \"2026-01-01 0000\", end: \"2026-03-01 2359\"}","handlingStrategy":"validation","validationCode":"// Client-side: estimate bucket count before sending\nlong stepMillis = step == Step.SECOND ? 1000L : step == Step.MINUTE ? 60_000L : step == Step.HOUR ? 3_600_000L : 86_400_000L;\nlong buckets = (endTs - startTs) / stepMillis;\nif (buckets > MAX_TIME_RANGE) {\n    throw new IllegalArgumentException(\"range too wide for step; coarsen step or split query\");\n}","typeGuard":null,"tryCatchPattern":"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; }","preventionTips":["Default dashboards to DAY/HOUR steps; require explicit opt-in for fine granularity.","Cap user-selected date ranges in UI relative to the chosen step.","Split long ranges into windows and aggregate client-side."],"tags":["query","duration","api-limit","graphql"],"backgroundTag":null,"analyzedSha":"102af09b4a56064e22050dded10e2c52e490d040","analyzedAt":"2026-08-14T10:47:52.647Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}