{"record":{"id":"ec67b1bc201f0655","repo":"python/cpython","slug":"eval-str-true-is-only-supported-with-format-format","errorCode":null,"errorMessage":"eval_str=True is only supported with format=Format.VALUE","messagePattern":"eval_str=True is only supported with format=Format\\.VALUE","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"Lib/annotationlib.py","lineNumber":959,"sourceCode":"\n      * If eval_str is true, eval() is called on values of type str.\n      * If eval_str is false (the default), values of type str are unchanged.\n\n    globals and locals are passed in to eval(); see the documentation\n    for eval() for more information.  If either globals or locals is\n    None, this function may replace that value with a context-specific\n    default, contingent on type(obj):\n\n      * If obj is a module, globals defaults to obj.__dict__.\n      * If obj is a class, globals defaults to\n        sys.modules[obj.__module__].__dict__ and locals\n        defaults to the obj class namespace.\n      * If obj is a callable, globals defaults to obj.__globals__,\n        although if obj is a wrapped function (using\n        functools.update_wrapper()) it is first unwrapped.\n    \"\"\"\n    if eval_str and format != Format.VALUE:\n        raise ValueError(\"eval_str=True is only supported with format=Format.VALUE\")\n\n    match format:\n        case Format.VALUE:\n            # For VALUE, we first look at __annotations__\n            ann = _get_dunder_annotations(obj)\n\n            # If it's not there, try __annotate__ instead\n            if ann is None:\n                ann = _get_and_call_annotate(obj, format)\n        case Format.FORWARDREF:\n            # For FORWARDREF, we use __annotations__ if it exists\n            try:\n                ann = _get_dunder_annotations(obj)\n            except Exception:\n                pass\n            else:\n                if ann is not None:\n                    return dict(ann)","sourceCodeStart":941,"sourceCodeEnd":977,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/annotationlib.py#L941-L977","documentation":"annotationlib.get_annotations() rejects eval_str=True unless format is Format.VALUE. eval_str exists to evaluate string annotations into objects, which is only meaningful in VALUE format; combining it with STRING or FORWARDREF is contradictory, so it raises ValueError immediately.","triggerScenarios":"get_annotations(func, eval_str=True, format=Format.STRING); get_annotations(cls, eval_str=True, format=Format.FORWARDREF); wrapping inspect.get_annotations-like logic while forwarding both parameters from user input.","commonSituations":"CLI/tooling exposing both eval_str and format flags and passing them through; porting code from inspect.get_annotations (which is implicitly VALUE-only) while adding a format argument; copy-pasted snippets mixing parameters.","solutions":["Drop the format argument (VALUE is the default) when you need eval_str=True.","Or set eval_str=False and post-process ForwardRef objects yourself when working in FORWARDREF format.","Validate the parameter pair at your own API boundary: reject eval_str and format != VALUE early with your own message."],"exampleFix":"# before\nann = get_annotations(func, eval_str=True, format=Format.FORWARDREF)  # ValueError\n\n# after\nann = get_annotations(func, eval_str=True)  # format defaults to Format.VALUE","handlingStrategy":"validation","validationCode":"from annotationlib import Format\n\ndef validate_get_annotations_kwargs(eval_str: bool, format=Format.VALUE):\n    if eval_str and format != Format.VALUE:\n        raise ValueError('eval_str=True requires the default VALUE format')","typeGuard":null,"tryCatchPattern":"try:\n    ann = get_annotations(obj, eval_str=eval_str, format=fmt)\nexcept ValueError as e:\n    if 'eval_str=True is only supported' in str(e):\n        ann = get_annotations(obj, eval_str=eval_str)  # retry with default VALUE format\n    else:\n        raise","preventionTips":["Never forward both eval_str and a non-VALUE format from tool flags","Default format to Format.VALUE in wrappers","Document that eval_str implies VALUE format"],"tags":["python","annotations","parameter-validation","get-annotations"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}