langflow-ai/langflow · warning · HTTPException
`since` must be strictly less than `until`
Error message
`since` must be strictly less than `until`
What it means
Validation error from GET /api/v1/authz/audit: when both since and until query params are supplied, since must be strictly less than until. since is an inclusive lower bound and until an exclusive upper bound on the audit timestamp, so an equal or inverted range is rejected with HTTP 400 before the query runs.
Source
Thrown at src/backend/base/langflow/api/v1/authz_audit.py:86
Query(description="Filter by action string, e.g. ``flow:read`` or ``share:create``."),
] = None,
result: Annotated[
str | None,
Query(description="Filter by decision result (``allow`` / ``deny`` / ``owner_override``)."),
] = None,
since: Annotated[datetime | None, Query(description="Inclusive lower bound on ``timestamp``.")] = None,
until: Annotated[datetime | None, Query(description="Exclusive upper bound on ``timestamp``.")] = None,
page: Annotated[int, Query(ge=1)] = 1,
size: Annotated[int, Query(ge=1, le=_MAX_PAGE_SIZE)] = 50,
) -> AuthzAuditPage:
"""Return a paginated slice of the audit log filtered by the given query params.
Superuser only. The composite indexes on ``(user_id, timestamp)`` and
``(resource_type, resource_id)`` keep both "show me events for user X"
and "show me events on resource Y" fast at scale.
"""
if since is not None and until is not None and since >= until:
raise HTTPException(status_code=400, detail="`since` must be strictly less than `until`")
base = select(AuthzAuditLog)
if user_id is not None:
base = base.where(AuthzAuditLog.user_id == user_id)
if resource_type is not None:
base = base.where(AuthzAuditLog.resource_type == resource_type)
if resource_id is not None:
base = base.where(AuthzAuditLog.resource_id == resource_id)
if action is not None:
base = base.where(AuthzAuditLog.action == action)
if result is not None:
base = base.where(AuthzAuditLog.result == result)
if since is not None:
base = base.where(AuthzAuditLog.timestamp >= since)
if until is not None:
base = base.where(AuthzAuditLog.timestamp < until)
# Two queries: one COUNT(*) for pagination metadata, one for the pageView on GitHub (pinned to 976ec789d2)
Solutions
- Ensure the client sends since < until strictly; when the picker returns equal timestamps, shift until forward by at least one second
- Send both timestamps in UTC with explicit offsets (e.g. Z) to avoid timezone inversion
- Validate the range client-side before issuing the request
- If you want a single instant, use only since and let until be null
Example fix
// before
const q = `?since=${start.toISOString()}&until=${end.toISOString()}`;
// after
if (since >= until) throw new RangeError('since must be < until');
const q = `?since=${start.toISOString()}&until=${end.toISOString()}`; Defensive patterns
Strategy: validation
Validate before calling
function validRange(since: Date, until: Date) {
return since.getTime() < until.getTime();
}
if (!validRange(since, until)) throw new RangeError('since must be < until'); Type guard
const isSafeRange = (s?: string, u?: string): boolean => s == null || u == null || new Date(s).getTime() < new Date(u).getTime();
Prevention
- Default date pickers to start-of-day / end-of-day rather than the same instant
- Always send UTC ISO strings with explicit offsets
- Client-side assert since < until before building the query string
When it happens
Trigger: GET /api/v1/authz/audit?since=2026-01-01T00:00:00Z&until=2026-01-01T00:00:00Z (equal bounds), or any range where since > until, e.g. copy-pasting timestamps with the times swapped or mixing timezone-offsets so the comparison inverts.
Common situations: UI date-range pickers that default start and end to the same instant, clients building ranges from two identical 'now' timestamps, or timezone confusion where an ISO string with +02:00 looks later than a UTC string but parses earlier.
Related errors
- resource_ids capped at {_MAX_RESOURCE_IDS}
- parent_role_id does not reference an existing role
- A role cannot be its own parent
- Failed to install MCP
- Invalid path
AI-assisted analysis of langflow-ai/langflow@976ec789d2 (2026-08-14).
Data as JSON: /api/errors/0b42aa05df761e63.
Report an issue: GitHub.