bitwarden/server · error · BadRequestException
Range too large.
Error message
Range too large.
What it means
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.
Source
Thrown at src/Api/Utilities/ApiHelpers.cs:102
/// If a time span greater than 367 days is passed will throw BadRequestException.
/// </remarks>
public static Tuple<DateTime, DateTime> GetDateRange(DateTime? start, DateTime? end)
{
if (!end.HasValue || !start.HasValue)
{
end = DateTime.UtcNow.Date.AddDays(1).AddMilliseconds(-1);
start = DateTime.UtcNow.Date.AddDays(-30);
}
else if (start.Value > end.Value)
{
var newEnd = start;
start = end;
end = newEnd;
}
if ((end.Value - start.Value) > TimeSpan.FromDays(367))
{
throw new BadRequestException("Range too large.");
}
return new Tuple<DateTime, DateTime>(start.Value, end.Value);
}
}
View on GitHub (pinned to e93b962371)
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.
Example fix
// before GET /events?start=2023-01-01&end=2025-01-01 // after (page 1) GET /events?start=2024-06-01&end=2024-12-01
Defensive patterns
Strategy: validation
Validate before calling
const MAX_RANGE_DAYS = 367;
function clampRange(start, end) {
if (end - start > MAX_RANGE_DAYS * 86_400_000) {
throw new Error(`Date range exceeds ${MAX_RANGE_DAYS} days; split the query.`);
}
return { start, end };
} Type guard
function isWithinRangeLimit(start: Date, end: Date): boolean {
return (end.getTime() - start.getTime()) <= 367 * 86_400_000;
} Prevention
- 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.
When it happens
Trigger: A GET /events (or any call site of GetDateRange) with `start` and `end` query parameters more than 367 days apart.
Common situations: 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.
Related errors
- The model state is invalid.
- User has existing keypair
- AccountKeys are only supported for V2 encryption.
- You cannot delete accounts owned by an organization. Contact
- You must be authenticated to create a request of that type.
AI-assisted analysis of bitwarden/server@e93b962371 (2026-08-13).
Data as JSON: /api/errors/3f9453ed035e08e9.
Report an issue: GitHub.