{"record":{"id":"c3e3ee688930e688","repo":"deepset-ai/haystack","slug":"can-t-compare-strings-using-operators","errorCode":null,"errorMessage":"Can't compare strings using operators '>', '>=', '<', '<='. Strings are only comparable if they are ISO formatted dates.","messagePattern":"Can't compare strings using operators '>', '>=', '<', '<='\\. Strings are only comparable if they are ISO formatted dates\\.","errorType":"exception","errorClass":"FilterError","httpStatus":null,"severity":"error","filePath":"haystack/utils/filters.py","lineNumber":182,"sourceCode":"    )\n    if not comparable:\n        return False\n    return value > filter_value\n\n\ndef _parse_date(value: str) -> datetime:\n    \"\"\"Try parsing the value as an ISO format date, then fall back to dateutil.parser.\"\"\"\n    try:\n        return datetime.fromisoformat(value)\n    except (ValueError, TypeError):\n        try:\n            return dateutil.parser.parse(value)\n        except (ValueError, TypeError) as exc:\n            msg = (\n                \"Can't compare strings using operators '>', '>=', '<', '<='. \"\n                \"Strings are only comparable if they are ISO formatted dates.\"\n            )\n            raise FilterError(msg) from exc\n\n\ndef _ensure_both_dates_naive_or_aware(date1: datetime, date2: datetime) -> tuple[datetime, datetime]:\n    \"\"\"Ensure that both dates are either naive or aware.\"\"\"\n    # Both naive\n    if date1.tzinfo is None and date2.tzinfo is None:\n        return date1, date2\n\n    # Both aware\n    if date1.tzinfo is not None and date2.tzinfo is not None:\n        return date1, date2\n\n    # One naive, one aware\n    if date1.tzinfo is None:\n        date1 = date1.replace(tzinfo=date2.tzinfo)\n    else:\n        date2 = date2.replace(tzinfo=date1.tzinfo)\n    return date1, date2","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/deepset-ai/haystack/blob/e318778c9bf60a1963e3b5f451359655dd696c30/haystack/utils/filters.py#L164-L200","documentation":"When comparing with ordering operators, plain strings are only interpretable if they are ISO-formatted dates; dateutil.parser.parse is used to convert them. If parsing fails, FilterError is raised because Haystack refuses to do arbitrary lexicographic string comparisons.","triggerScenarios":"Filters like {\"operator\": \">\", \"field\": \"meta.created\", \"value\": \"March 2024\"} or non-date strings such as 'abc' compared with >, >=, <, <=.","commonSituations":"Storing human-readable dates in metadata instead of ISO 8601; comparing free-text fields with ordering operators; timezone-aware vs naive ISO strings.","solutions":["Use ISO 8601 strings, e.g. '2024-03-01' or '2024-03-01T00:00:00'.","Compare datetime.datetime objects instead of strings.","For non-date strings, don't use ordering operators — use '=='/'in' or store a sortable key."],"exampleFix":"// before\nfilters = {\"operator\": \">\", \"field\": \"meta.date\", \"value\": \"March 3rd 2024\"}\n// after\nfilters = {\"operator\": \">\", \"field\": \"meta.date\", \"value\": \"2024-03-03\"}","handlingStrategy":"validation","validationCode":"from dateutil import parser\ntry:\n    parser.isoparse(value)\nexcept (ValueError, TypeError):\n    raise ValueError(\"use ISO 8601 dates for string comparisons\")","typeGuard":"def is_iso_date(s: str) -> bool:\n    try:\n        dateutil.parser.isoparse(s)\n        return True\n    except (ValueError, TypeError):\n        return False","tryCatchPattern":"try:\n    ok = document_matches_filter(doc, filters)\nexcept FilterError:\n    ok = False","preventionTips":["Store metadata dates as ISO 8601 strings or datetime objects.","Never use >,< on free-text string fields.","Normalize dates at ingestion time."],"tags":["python","filters","datetime","haystack"],"backgroundTag":"invalid-date-format","analyzedSha":"e318778c9bf60a1963e3b5f451359655dd696c30","analyzedAt":"2026-08-30T11:45:20.711Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}