{"record":{"id":"ded07bd6b0cc6ebb","repo":"OpenBB-finance/OpenBB","slug":"query-string-is-empty-or-invalid-query","errorCode":null,"errorMessage":"Query string is empty or invalid -> '{query}'","messagePattern":"Query string is empty or invalid -> '(.+?)'","errorType":"validation","errorClass":"OpenBBError","httpStatus":null,"severity":"error","filePath":"openbb_platform/providers/imf/openbb_imf/utils/metadata.py","lineNumber":130,"sourceCode":"\n    def search_dataflows(self, query: str) -> list[dict]:\n        \"\"\"Search dataflows based on a query string.\n\n        Parameters\n        ----------\n        query : str\n            The search query string, which can include AND (+) and OR (|) operators,\n            as well as quoted phrases for exact matches.\n        Returns\n        -------\n        list[dict]\n            A list of matching dataflows, grouped by their structureRef ID.\n        \"\"\"\n        grouped_results: dict = {}\n        parsed_query = self._parse_query(query)\n\n        if not parsed_query:\n            raise OpenBBError(\n                ValueError(f\"Query string is empty or invalid -> '{query}'\")\n            )\n\n        for dataflow_obj in self.dataflows.values():\n            dataflow_id = dataflow_obj.get(\"id\", \"\").lower()\n            dataflow_name = dataflow_obj.get(\"name\", \"\").lower()\n            dataflow_description = dataflow_obj.get(\"description\", \"\").lower()\n            dataflow_matches = False\n\n            for or_group in parsed_query:\n                or_group_matches_all_and_terms = True\n\n                for and_term in or_group:\n                    if not (\n                        and_term in dataflow_id\n                        or and_term in dataflow_name\n                        or and_term in dataflow_description\n                    ):","sourceCodeStart":112,"sourceCodeEnd":148,"githubUrl":"https://github.com/OpenBB-finance/OpenBB/blob/3e071fcc2cd9f891cac6040ae60296dba76dab46/openbb_platform/providers/imf/openbb_imf/utils/metadata.py#L112-L148","documentation":"Raised by search_dataflows on the IMF metadata object when _parse_query returns an empty structure for the supplied query string. The parser understands AND ('+' or implicit) and OR ('|') operators plus quoted phrases; a string consisting only of operators, whitespace, or unbalanced quotes parses to nothing and is rejected here before any matching runs.","triggerScenarios":"query='+', query='|', query='\"', query='   ', or a query built by joining an empty/whitespace term list with operators (e.g. '+'.join(terms) with terms all empty).","commonSituations":"Programmatically assembled queries from optional filters where all filters are blank; users quoting phrases but leaving the closing quote off; copy-paste introducing stray operator characters.","solutions":["Provide at least one real search term: query='trade', query='balance+payments', query='goods|services'.","Sanitize built queries: strip operator-only results and require a non-empty term list before calling.","Use quoted phrases for multi-word matches: query='\"direction of trade\"'."],"exampleFix":"# before\nterms = [t for t in user_filters if selected.get(t)]  # all empty\nmeta.search_dataflows(query='+'.join(terms))\n\n# after\nterms = [t.strip() for t in user_filters if selected.get(t) and t.strip()]\nif not terms:\n    raise ValueError('At least one search term is required.')\nmeta.search_dataflows(query='+'.join(terms))","handlingStrategy":"validation","validationCode":"import re\ndef build_query(terms: list[str]) -> str | None:\n    cleaned = [t.strip() for t in terms if t and t.strip()]\n    if not cleaned:\n        return None\n    return '+'.join(cleaned)\n\nq = build_query(terms)\nif q is None:\n    raise ValueError('At least one search term is required.')\nresults = meta.search_dataflows(query=q)","typeGuard":"def is_parseable_search_query(q: str | None) -> bool:\n    if not q:\n        return False\n    # at least one alphanumeric token outside quotes/operators\n    return bool(re.search(r'[A-Za-z0-9]', q.replace('\"', '')))","tryCatchPattern":"try:\n    results = meta.search_dataflows(query=q)\nexcept OpenBBError as e:\n    if 'empty or invalid' in str(e):\n        results = list(meta.dataflows.values())  # or prompt user for a term\n    else:\n        raise","preventionTips":["Require at least one alphanumeric term before calling search.","Test query builders with all-empty filter sets.","Quote multi-word phrases fully ('\"direction of trade\"')."],"tags":["validation","imf","search","metadata","query-syntax"],"backgroundTag":null,"analyzedSha":"3e071fcc2cd9f891cac6040ae60296dba76dab46","analyzedAt":"2026-08-14T23:40:48.960Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}