langgenius/dify · warning

{str(exc)}

Error message

{str(exc)}

What it means

Flask `abort(400, description=str(exc))` (HTTP 400) raised inside `_parse_observability_time_range` (api/controllers/console/agent/roster.py:538). It wraps `libs.datetime_utils.parse_time_range`, which raises ValueError on malformed time strings (expected format `YYYY-MM-DD HH:MM`), invalid timezone names, or when start > end. The helper uses `account.timezone or 'UTC'` as the timezone.

Source

Thrown at api/controllers/console/agent/roster.py:538

        info_endpoint=f"{base_url}/info",
        meta_endpoint=f"{base_url}/meta",
        api_rpm=app_model.api_rpm or 0,
        api_rph=app_model.api_rph or 0,
        api_key_count=_agent_api_key_count(session, str(app_model.id)),
    )
    return response.model_dump(mode="json")


def _agent_observability_service(session: Session) -> AgentObservabilityService:
    return AgentObservabilityService(session)


def _parse_observability_time_range(start: str | None, end: str | None, account: Account):
    timezone = account.timezone or "UTC"
    try:
        return parse_time_range(start, end, timezone)
    except ValueError as exc:
        abort(400, description=str(exc))


def _query_values(name: str, alias_name: str | None = None) -> list[str]:
    def _get_values(field_name: str) -> list[str]:
        values = request.args.getlist(field_name)
        indexed_values: list[tuple[int, list[str]]] = []
        prefix = f"{field_name}["
        for key in request.args:
            if not key.startswith(prefix) or not key.endswith("]"):
                continue
            index = key[len(prefix) : -1]
            if index.isdigit():
                indexed_values.append((int(index), request.args.getlist(key)))
        for _, items in sorted(indexed_values):
            values.extend(items)
        return values

    values = _get_values(name)

View on GitHub (pinned to ef8544b173)

Solutions

  1. Send `start` and `end` in the exact `YYYY-MM-DD HH:MM` format with URL encoding for the space.
  2. Ensure `start <= end` and that both fall on valid calendar dates.
  3. Verify the user's account timezone is a valid IANA name; rely on the 'UTC' fallback only if unset.

Example fix

// before
GET /agent/<id>/logs?start=2024-01-01&end=2024-02-01
// after (correct format with encoded space)
GET /agent/<id>/logs?start=2024-01-01%2000:00&end=2024-02-01%2000:00
Defensive patterns

Strategy: validation

Validate before calling

import datetime, pytz

TIME_FMT = "%Y-%m-%d %H:%M"

def valid_time_range(start, end, tzname="UTC"):
    tz = pytz.timezone(tzname or "UTC")  # raises UnknownTimeZoneError early
    s = datetime.datetime.strptime(start, TIME_FMT) if start else None
    e = datetime.datetime.strptime(end, TIME_FMT) if end else None
    if s and e and s > e:
        raise ValueError("start must be <= end")
    return True

Type guard

import datetime, re

_TIME_RE = re.compile(r"^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$")

def is_valid_range_str(value: str | None) -> bool:
    return value is None or bool(_TIME_RE.match(value) and _parses(value))

def _parses(value):
    try:
        datetime.datetime.strptime(value, "%Y-%m-%d %H:%M")
        return True
    except ValueError:
        return False

Try / catch

try:
    resp = client.get(f"/console/api/agent/{aid}/logs", params={"start": s, "end": e})
except HTTPError as err:
    if err.response.status_code == 400:
        raise ValueError(f"bad time range: {err.response.json().get('description')}") from err
    raise

Prevention

When it happens

Trigger: An agent observability endpoint that calls `_parse_observability_time_range` receives a `start`/`end` query string that fails `parse_time_range` parsing: wrong format, unknown timezone on the account, or a start later than end.

Common situations: Client sends `?start=2024-13-01 10:00` (bad month), omits the time portion (`2024-01-01`), passes a swapped range, or the user's `account.timezone` is unset to an invalid tzdb name.

Related errors


AI-assisted analysis of langgenius/dify@ef8544b173 (2026-08-12). Data as JSON: /api/errors/f2ef56beccd86a7c. Report an issue: GitHub.