{"record":{"id":"d123c114a84647cc","repo":"infiniflow/ragflow","slug":"querit-time-range-must-use-dn-wn-mn-yn-or-yyyy","errorCode":null,"errorMessage":"Querit time_range must use dN, wN, mN, yN, or YYYY-MM-DDtoYYYY-MM-DD.","messagePattern":"Querit time_range must use dN, wN, mN, yN, or YYYY-MM-DDtoYYYY-MM-DD\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/tools/querit.py","lineNumber":412,"sourceCode":"\n\ndef _validate_search_inputs(\n    count: Any,\n    chunks_per_doc: Any,\n    time_range: Any,\n    site_include: Any,\n    site_exclude: Any,\n    country_include: Any,\n    language_include: Any,\n) -> None:\n    if type(count) is not int or count < 1:\n        raise ValueError(\"Querit count must be an integer greater than or equal to 1.\")\n    if chunks_per_doc is not None and (type(chunks_per_doc) is not int or not 1 <= chunks_per_doc <= 3):\n        raise ValueError(\"Querit chunks_per_doc must be an integer from 1 to 3.\")\n    if type(time_range) is not str:\n        raise ValueError(\"Querit time_range must be a string.\")\n    if time_range and not TIME_RANGE_PATTERN.fullmatch(time_range):\n        raise ValueError(\"Querit time_range must use dN, wN, mN, yN, or YYYY-MM-DDtoYYYY-MM-DD.\")\n    for name, value in (\n        (\"site_include\", site_include),\n        (\"site_exclude\", site_exclude),\n        (\"country_include\", country_include),\n        (\"language_include\", language_include),\n    ):\n        if not isinstance(value, list) or any(not isinstance(item, str) for item in value):\n            raise ValueError(f\"Querit {name} must be an array of strings.\")\n\n\ndef _safe_error_message(error: Exception, api_key: str) -> str:\n    message = str(error) or error.__class__.__name__\n    return message.replace(api_key, \"[REDACTED]\") if api_key else message\n\n\ndef _querit_text(value: Any) -> str:\n    return \"\" if value is None else str(value)\n","sourceCodeStart":394,"sourceCodeEnd":430,"githubUrl":"https://github.com/infiniflow/ragflow/blob/554fb1133ac3861732235ad9c377eb5e0a770665/agent/tools/querit.py#L394-L430","documentation":"The Querit agent tool validates its time_range parameter against TIME_RANGE_PATTERN = ^([dwmy][1-9][0-9]*|\\d{4}-\\d{2}-\\d{2}to\\d{4}-\\d{2}-\\d{2})$ in _validate_search_inputs (agent/tools/querit.py:411). Any non-empty string that does not exactly match 'dN'/'wN'/'mN'/'yN' (N >= 1, no leading zero) or a literal 'YYYY-MM-DDtoYYYY-MM-DD' range raises ValueError before any API call is made. An empty string is allowed and means 'no time restriction'.","triggerScenarios":"Calling the Querit component with time_range set to values like 'last 7 days', '7d' (prefix must come first), 'w0' or 'm' (N must be >= 1), '2024/01/01to2024/12/31' (slashes instead of dashes), '2024-01-01 to 2024-12-31' (spaces), or 'd7 ' (trailing whitespace defeats fullmatch). LLM-generated tool arguments that paraphrase the range instead of using the DSL are the most common producer.","commonSituations":"Users copy human-readable ranges from other search tools; day-first date formats; an LLM agent component fills time_range free-form; leading-zero counts like 'd07'.","solutions":["Use the relative form: one letter d/w/m/y immediately followed by an integer >= 1 with no leading zero (e.g. 'd7', 'w4', 'm12', 'y1').","Or use the absolute form with no spaces: '2024-01-01to2024-12-31' (ISO dates joined by the literal 'to').","Pass an empty string (or omit the parameter) if you want no time filter.","If you keep failing, test your value against the exact regex: re.fullmatch(r'([dwmy][1-9][0-9]*|\\d{4}-\\d{2}-\\d{2}to\\d{4}-\\d{2}-\\d{2})', value)."],"exampleFix":"// before (canvas / tool params)\n\"time_range\": \"last 7 days\"\n\n// after\n\"time_range\": \"d7\"","handlingStrategy":"validation","validationCode":"import re\nTIME_RANGE = re.compile(r\"([dwmy][1-9][0-9]*|\\d{4}-\\d{2}-\\d{2}to\\d{4}-\\d{2}-\\d{2})\")\n\ndef valid_time_range(v):\n    return isinstance(v, str) and (v == \"\" or TIME_RANGE.fullmatch(v))","typeGuard":"def is_querit_time_range(value) -> bool:\n    if not isinstance(value, str):\n        return False\n    return value == \"\" or bool(re.fullmatch(r\"[dwmy][1-9][0-9]*|\\d{4}-\\d{2}-\\d{2}to\\d{4}-\\d{2}-\\d{2}\", value))","tryCatchPattern":"try:\n    querit.run(time_range=tr)\nexcept ValueError as e:\n    if \"time_range\" in str(e):\n        tr = \"\"  # fall back to no restriction\n        querit.run(time_range=tr)","preventionTips":["Build time_range programmatically (e.g. f'd{days}') instead of typing free text.","When an LLM generates the parameter, add the DSL grammar to the tool description or few-shot examples.","Prefer the relative dN/wN/mN/yN form unless an exact window is required.","Validate with the same regex before invoking the component."],"tags":["validation","agent","querit","time-range","regex"],"backgroundTag":null,"analyzedSha":"554fb1133ac3861732235ad9c377eb5e0a770665","analyzedAt":"2026-08-15T09:20:16.380Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}