{"record":{"id":"212082a594778bce","repo":"xtekky/gpt4free","slug":"cannot-access-field-part-r-on-non-dict-value-whi","errorCode":null,"errorMessage":"Cannot access field {part!r} on non-dict value while resolving {value!r}","messagePattern":"Cannot access field (.+?) on non-dict value while resolving (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"g4f/providers/config_provider.py","lineNumber":291,"sourceCode":"        # 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}\")\n\n        result = variables[root]\n        for part in parts[1:]:\n            if isinstance(result, dict):\n                result = result.get(part)\n                if result is None:\n                    result = 0.0\n                    break\n            else:\n                raise ValueError(\n                    f\"Cannot access field {part!r} on non-dict value \"\n                    f\"while resolving {value!r}\"\n                )\n\n        return float(result) if result is not None else 0.0, pos\n    else:\n        raise ValueError(f\"Unexpected token {kind!r}={value!r} in condition expression\")\n\n\ndef evaluate_condition(\n    condition: str,\n    quota: Optional[Dict],\n    error_count: int,\n) -> bool:\n    \"\"\"Evaluate a provider condition string.\n\n    The condition may reference:\n","sourceCodeStart":273,"sourceCodeEnd":309,"githubUrl":"https://github.com/xtekky/gpt4free/blob/973504e1770928ed5fb82f43da528f441ad9ddc3/g4f/providers/config_provider.py#L273-L309","documentation":"ValueError raised while resolving a dotted variable in a config.yaml condition: the root resolved successfully, but an intermediate segment was not a dict, so result.get(part) is impossible. E.g. 'quota.balance.free' where quota.balance is already a number. The message names the offending field and the full dotted path.","triggerScenarios":"A condition walks deeper than the data shape: 'quota.balance.remaining > 0' when quota.balance is a float, or 'quota.x.y' where quota.x is a list/string.","commonSituations":"Providers whose get_quota() returns flat numbers where the condition expects nested dicts; conditions written against a different provider's quota schema; schema drift after a provider update changes nesting.","solutions":["Inspect the provider's actual get_quota() output and flatten the condition to stop at the scalar level ('quota.balance > 0').","If multiple providers share one config, give each provider its own correctly-shaped condition instead of one generic condition.","Test with evaluate_condition(condition, await provider.get_quota(), 0) before deploying config.yaml.","Update g4f — quota schemas are occasionally normalized across providers."],"exampleFix":"# before (config.yaml)\ncondition: \"quota.balance.remaining > 0\"\n\n# after\ncondition: \"quota.balance > 0\"","handlingStrategy":"validation","validationCode":"quota = await provider.get_quota() if hasattr(provider, 'get_quota') else None\nif quota is not None:\n    evaluate_condition(condition, quota, 0)  # raises here, not mid-request, if paths mismatch","typeGuard":"def path_is_numeric(quota: dict, dotted: str) -> bool:\n    node = quota\n    for part in dotted.split('.'):\n        if not isinstance(node, dict) or part not in node:\n            return False\n        node = node[part]\n    return isinstance(node, (int, float))","tryCatchPattern":null,"preventionTips":["Print the provider's real get_quota() shape before writing conditions.","Stop dotted paths at the first scalar level.","Re-validate conditions whenever a provider's quota schema changes."],"tags":["config","yaml","condition-parser","schema-mismatch","g4f"],"backgroundTag":null,"analyzedSha":"973504e1770928ed5fb82f43da528f441ad9ddc3","analyzedAt":"2026-08-14T23:45:32.408Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}