{"record":{"id":"3f9453ed035e08e9","repo":"bitwarden/server","slug":"range-too-large","errorCode":null,"errorMessage":"Range too large.","messagePattern":"Range too large\\.","errorType":"validation","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"src/Api/Utilities/ApiHelpers.cs","lineNumber":102,"sourceCode":"    /// If a time span greater than 367 days is passed will throw BadRequestException.\n    /// </remarks>\n    public static Tuple<DateTime, DateTime> GetDateRange(DateTime? start, DateTime? end)\n    {\n        if (!end.HasValue || !start.HasValue)\n        {\n            end = DateTime.UtcNow.Date.AddDays(1).AddMilliseconds(-1);\n            start = DateTime.UtcNow.Date.AddDays(-30);\n        }\n        else if (start.Value > end.Value)\n        {\n            var newEnd = start;\n            start = end;\n            end = newEnd;\n        }\n\n        if ((end.Value - start.Value) > TimeSpan.FromDays(367))\n        {\n            throw new BadRequestException(\"Range too large.\");\n        }\n\n        return new Tuple<DateTime, DateTime>(start.Value, end.Value);\n    }\n}\n","sourceCodeStart":84,"sourceCodeEnd":108,"githubUrl":"https://github.com/bitwarden/server/blob/e93b962371d80964556f5590c6615f5160a437a1/src/Api/Utilities/ApiHelpers.cs#L84-L108","documentation":"ApiHelpers.GetDateRange (used by the events/audit endpoints) defaults a null range to the last 30 days, swaps reversed start/end, then enforces a hard ceiling: the span must not exceed 367 days. A range wider than one year plus two days is rejected as HTTP 400.","triggerScenarios":"A GET /events (or any call site of GetDateRange) with `start` and `end` query parameters more than 367 days apart.","commonSituations":"Exporting a full audit/event history; a date picker defaulting to 'all time'; a client computing end-minus-start incorrectly (off-by-year); calendar widgets that round to year boundaries.","solutions":["Split the query into multiple paginated calls, each spanning no more than 367 days.","Narrow the date-picker default range to <= 367 days.","If you control the server, confirm 367 days is the intended cap before changing the constant."],"exampleFix":"// before\nGET /events?start=2023-01-01&end=2025-01-01\n// after (page 1)\nGET /events?start=2024-06-01&end=2024-12-01","handlingStrategy":"validation","validationCode":"const MAX_RANGE_DAYS = 367;\nfunction clampRange(start, end) {\n  if (end - start > MAX_RANGE_DAYS * 86_400_000) {\n    throw new Error(`Date range exceeds ${MAX_RANGE_DAYS} days; split the query.`);\n  }\n  return { start, end };\n}","typeGuard":"function isWithinRangeLimit(start: Date, end: Date): boolean {\n  return (end.getTime() - start.getTime()) <= 367 * 86_400_000;\n}","tryCatchPattern":null,"preventionTips":["Default date pickers to <= 367 days for event/audit views.","For large histories, page through time windows client-side.","Never assume an uncapped range is accepted by the events API."],"tags":["date-range","events","validation","bad-request"],"backgroundTag":null,"analyzedSha":"e93b962371d80964556f5590c6615f5160a437a1","analyzedAt":"2026-08-13T14:22:19.382Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}