{"record":{"id":"28feab7da5ea7925","repo":"pola-rs/polars","slug":"require-dict-mapping","errorCode":null,"errorMessage":"require dict mapping","messagePattern":"require dict mapping","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"py-polars/src/polars/_utils/udfs.py","lineNumber":725,"sourceCode":"                return f\"{op}{e1}\"\n            else:\n                e2 = self._expr(value.right_operand, col, param_name, depth + 1)\n                if op in (\"is\", \"is not\") and value.left_operand == \"None\":\n                    not_ = \"\" if op == \"is\" else \"not_\"\n                    return f\"{e1}.is_{not_}null()\"\n                elif op in (\"in\", \"not in\"):\n                    not_ = \"\" if op == \"in\" else \"~\"\n                    return (\n                        f\"{not_}({e1}.is_in({e2}))\"\n                        if \" \" in e1\n                        else f\"{not_}{e1}.is_in({e2})\"\n                    )\n                elif op == \"replace_strict\":\n                    if not self._caller_variables:\n                        self._caller_variables = _get_all_caller_variables()\n                    if not isinstance(self._caller_variables.get(e1, None), dict):\n                        msg = \"require dict mapping\"\n                        raise NotImplementedError(msg)\n                    return f\"{e2}.{op}({e1})\"\n                elif op == \"<<\":\n                    # 2**e2 may be float if e2 was -ve, but if e1 << e2 was valid then\n                    # e2 must have been +ve. therefore 2**e2 can be safely cast to\n                    # i64, which may be necessary if chaining ops that assume i64.\n                    return f\"({e1} * 2**{e2}).cast(pl.Int64)\"\n                elif op == \">>\":\n                    # (motivation for the cast is same as the '<<' case above)\n                    return f\"({e1} / 2**{e2}).cast(pl.Int64)\"\n                else:\n                    expr = f\"{e1} {op} {e2}\"\n                    return f\"({expr})\" if depth else expr\n\n        elif value == param_name:\n            return f'pl.col(\"{col}\")'\n\n        return value\n","sourceCodeStart":707,"sourceCodeEnd":743,"githubUrl":"https://github.com/pola-rs/polars/blob/fe841f959ef4d2ceefc05a310d33ed7b1ab24e5e/py-polars/src/polars/_utils/udfs.py#L707-L743","documentation":"When translating a UDF that calls dict.replace_strict (or a mapped replace_strict via a variable looked up in the caller's frame), the parser requires that the referenced variable be a plain dict so it can inline it as a mapping. If the caller-local variable resolved by name is not a dict, NotImplementedError('require dict mapping') is raised.","triggerScenarios":"Inside a map_elements UDF, calling something.replace_strict(x) where x is a local variable in the enclosing function that is not a dict (e.g. a Series, defaultdict-like wrapper, or non-dict mapping); detected via _get_all_caller_variables in _expr.","commonSituations":"Passing a collections.OrderedDict subclass, a polars Series, or a custom Mapping to replace_strict from within a UDF; defining the mapping in an outer scope the parser cannot resolve as a dict.","solutions":["Make the mapping a plain built-in dict literal or dict variable visible to the UDF's caller scope.","Use replace (non-strict) or explicit when/then chains instead of replace_strict with a non-dict mapping.","Perform the replacement outside the UDF using a native expression: pl.col('a').replace_strict(mapping)."],"exampleFix":"// before\ndef fn(v): return str(v).replace_strict(labels)\n// after\nlabels = {'a': 1, 'b': 2}  # plain dict in caller scope\ndef fn(v): return v.replace_strict(labels)","handlingStrategy":"type-guard","validationCode":"# before using replace_strict inside a UDF, ensure the mapping is a plain dict\nassert isinstance(labels, dict), 'replace_strict mapping must be a plain dict'","typeGuard":"def is_plain_dict(v) -> bool:\n    return type(v) is dict","tryCatchPattern":"try:\n    result = df.select(pl.col('a').map_elements(fn))\nexcept NotImplementedError as e:\n    if 'require dict mapping' in str(e):\n        result = df.select(pl.col('a').replace_strict(dict(labels)))","preventionTips":["Use plain dict literals for replace_strict mappings","Keep mappings in the immediate caller scope of the UDF","Do the replacement natively: pl.col('a').replace_strict(mapping)"],"tags":["python","polars","udf","dict"],"backgroundTag":"invalid-argument-value","analyzedSha":"fe841f959ef4d2ceefc05a310d33ed7b1ab24e5e","analyzedAt":"2026-09-18T22:14:11.667Z","contentChangedAt":"2026-09-18T22:14:11.667Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}