{"record":{"id":"12273b0bb739f1f0","repo":"langgenius/dify","slug":"str-e-12273b","errorCode":null,"errorMessage":"{str(e)}","messagePattern":"\\{str\\(e\\)\\}","errorType":"http","errorClass":null,"httpStatus":400,"severity":"warning","filePath":"api/controllers/console/app/conversation.py","lineNumber":136,"sourceCode":"\n        if req_data.keyword:\n            from libs.helper import escape_like_pattern\n\n            escaped_keyword = escape_like_pattern(req_data.keyword)\n            query = query.join(Message, Message.conversation_id == Conversation.id).where(\n                or_(\n                    Message.query.ilike(f\"%{escaped_keyword}%\", escape=\"\\\\\"),\n                    Message.answer.ilike(f\"%{escaped_keyword}%\", escape=\"\\\\\"),\n                )\n            )\n\n        account = current_user\n        assert account.timezone is not None\n\n        try:\n            start_datetime_utc, end_datetime_utc = parse_time_range(req_data.start, req_data.end, account.timezone)\n        except ValueError as e:\n            abort(400, description=str(e))\n\n        if start_datetime_utc:\n            query = query.where(Conversation.created_at >= start_datetime_utc)\n\n        if end_datetime_utc:\n            end_datetime_utc = end_datetime_utc.replace(second=59)\n            query = query.where(Conversation.created_at < end_datetime_utc)\n\n        # FIXME, the type ignore in this file\n        if req_data.annotation_status == \"annotated\":\n            query = (\n                query.options(selectinload(Conversation.message_annotations))  # type: ignore[arg-type]\n                .join(  # type: ignore\n                    MessageAnnotation, MessageAnnotation.conversation_id == Conversation.id\n                )\n                .group_by(Conversation.id)\n            )\n        elif req_data.annotation_status == \"not_annotated\":","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/langgenius/dify/blob/ef8544b173fd6cd7a8e71df2cab576e52bebbfbc/api/controllers/console/app/conversation.py#L118-L154","documentation":"Flask `abort(400, description=str(e))` (HTTP 400) at api/controllers/console/app/conversation.py:136 in the conversation list handler. `parse_time_range(req_data.start, req_data.end, account.timezone)` raises ValueError for malformed `YYYY-MM-DD HH:MM` inputs, an invalid `account.timezone`, or start > end. The handler asserts `account.timezone is not None` immediately before, so a None timezone would surface as an AssertionError (500), not this 400.","triggerScenarios":"Calling the conversation list API with `start`/`end` query params that fail `parse_time_range`, e.g. wrong datetime format, an unknown IANA timezone on the user account, or a start that is later than end.","commonSituations":"Frontend sends an ISO timestamp (`2024-01-01T00:00:00Z`) instead of the expected `YYYY-MM-DD HH:MM`, or the user's account timezone is set to a name pytz cannot resolve.","solutions":["Format both `start` and `end` as `YYYY-MM-DD HH:MM` (URL-encode the space).","Ensure `account.timezone` is a valid IANA zone (e.g. 'America/New_York') before calling.","Guarantee `start <= end`."],"exampleFix":"// before\nGET /apps/<id>/conversations?start=2024-01-01T00:00:00Z\n// after\nGET /apps/<id>/conversations?start=2024-01-01%2000:00","handlingStrategy":"validation","validationCode":"import datetime, pytz\nTIME_FMT = \"%Y-%m-%d %H:%M\"\npytz.timezone(account.timezone)  # fails fast on bad tz\nif req_data.start: datetime.datetime.strptime(req_data.start, TIME_FMT)\nif req_data.end:   datetime.datetime.strptime(req_data.end, TIME_FMT)","typeGuard":"import datetime, re\n_RE = re.compile(r\"^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}$\")\ndef is_valid_range_str(v: str | None) -> bool:\n    if not v:\n        return True\n    if not _RE.match(v):\n        return False\n    try:\n        datetime.datetime.strptime(v, \"%Y-%m-%d %H:%M\")\n        return True\n    except ValueError:\n        return False","tryCatchPattern":"try:\n    resp = client.get(f\"/console/api/apps/{app_id}/conversations\", params=p)\nexcept HTTPError as err:\n    if err.response.status_code == 400:\n        raise ValueError(f\"bad time range: {err.response.text}\") from err\n    raise","preventionTips":["Always format bounds as `YYYY-MM-DD HH:MM` and URL-encode the space.","Validate `account.timezone` is a valid IANA name on profile save.","Send start <= end."],"tags":["validation","datetime","http-400","conversation","app"],"backgroundTag":null,"analyzedSha":"ef8544b173fd6cd7a8e71df2cab576e52bebbfbc","analyzedAt":"2026-08-12T05:15:17.394Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}