{"record":{"id":"3b5005aff70d8c1a","repo":"xtekky/gpt4free","slug":"unexpected-end-of-condition-expression","errorCode":null,"errorMessage":"Unexpected end of condition expression","messagePattern":"Unexpected end of condition expression","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"g4f/providers/config_provider.py","lineNumber":263,"sourceCode":"        if pos < len(tokens) and tokens[pos][0] == \"rp\":\n            pos += 1  # consume ')'\n        return val, pos\n\n    left_val, pos = _parse_atom(tokens, pos, variables)\n\n    if pos < len(tokens) and tokens[pos][0] == \"op\":\n        op_str = tokens[pos][1]\n        pos += 1\n        right_val, pos = _parse_atom(tokens, pos, variables)\n        return _OPS[op_str](left_val, right_val), pos\n\n    # Bare value – treat as truthy\n    return bool(left_val), pos\n\n\ndef _parse_atom(tokens, pos, variables):\n    if pos >= len(tokens):\n        raise ValueError(\"Unexpected end of condition expression\")\n\n    kind, value = tokens[pos]\n    pos += 1\n\n    if kind == \"float\":\n        return float(value), pos\n    elif kind == \"int\":\n        return int(value), pos\n    elif kind == \"id\":\n        # Legacy alias: \"get_quota.balance\" → \"quota.balance\"\n        if value == \"get_quota.balance\":\n            value = \"quota.balance\"\n\n        # Resolve dotted paths: \"quota.credits.remaining\", \"balance\", etc.\n        parts = value.split(\".\")\n        root = parts[0]\n        if root not in variables:\n            raise ValueError(f\"Unknown variable in condition: {root!r}\")","sourceCodeStart":245,"sourceCodeEnd":281,"githubUrl":"https://github.com/xtekky/gpt4free/blob/973504e1770928ed5fb82f43da528f441ad9ddc3/g4f/providers/config_provider.py#L245-L281","documentation":"ValueError from the recursive-descent condition parser in config_provider: while parsing a config.yaml provider condition, _parse_atom (or its callers) ran out of tokens before completing the expression. This is a syntax error in the condition string — e.g. it ends with a dangling operator or an incomplete comparison.","triggerScenarios":"A config.yaml provider entry has a condition like 'quota.credits.remaining >' or 'balance ==' (or an empty operand after an operator); evaluate_condition tokenizes it and _parse_atom hits pos >= len(tokens).","commonSituations":"Hand-editing config.yaml and truncating a condition; YAML folding/quoting splitting a condition string; upgrading g4f and older condition syntax no longer parsing to a complete token stream.","solutions":["Open config.yaml and complete the malformed condition: every operator needs a right-hand operand (e.g. 'quota.credits.remaining > 0').","Validate YAML quoting — keep conditions on one line or use quoted folded scalars so tokens are not lost.","Run a quick parse check: from g4f.providers.config_provider import evaluate_condition; evaluate_condition('<condition>', {}, 0) to test in isolation.","Comment out the offending provider entry to restore service, then fix and re-enable."],"exampleFix":"# before (config.yaml)\ncondition: \"quota.credits.remaining >\"\n\n# after\ncondition: \"quota.credits.remaining > 0\"","handlingStrategy":"validation","validationCode":"from g4f.providers.config_provider import evaluate_condition\nfor cond in my_conditions:  # gathered from config.yaml before deployment\n    try:\n        evaluate_condition(cond, {'quota': {'balance': 1.0}}, 0)\n    except ValueError as e:\n        raise ValueError(f'bad config.yaml condition {cond!r}: {e}') from e","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Lint every condition in config.yaml with evaluate_condition at startup.","Keep conditions on a single YAML line, fully quoted.","Every operator needs a right-hand operand; no trailing operators."],"tags":["config","yaml","condition-parser","validation","g4f"],"backgroundTag":null,"analyzedSha":"973504e1770928ed5fb82f43da528f441ad9ddc3","analyzedAt":"2026-08-14T23:45:32.408Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}