{"record":{"id":"fd3f7d25d5638f02","repo":"nodejs/node","slug":"cannot-assign-attribute-on-non-namespace-object","errorCode":null,"errorMessage":"cannot assign attribute on non-namespace object","messagePattern":"cannot assign attribute on non-namespace object","errorType":"exception","errorClass":"TemplateRuntimeError","httpStatus":null,"severity":"error","filePath":"tools/inspector_protocol/jinja2/compiler.py","lineNumber":1425,"sourceCode":"        # instruction indicates a parameter which are always defined.\n        if node.ctx == 'load':\n            load = frame.symbols.find_load(ref)\n            if not (load is not None and load[0] == VAR_LOAD_PARAMETER and \\\n                    not self.parameter_is_undeclared(ref)):\n                self.write('(undefined(name=%r) if %s is missing else %s)' %\n                           (node.name, ref, ref))\n                return\n\n        self.write(ref)\n\n    def visit_NSRef(self, node, frame):\n        # NSRefs can only be used to store values; since they use the normal\n        # `foo.bar` notation they will be parsed as a normal attribute access\n        # when used anywhere but in a `set` context\n        ref = frame.symbols.ref(node.name)\n        self.writeline('if not isinstance(%s, Namespace):' % ref)\n        self.indent()\n        self.writeline('raise TemplateRuntimeError(%r)' %\n                       'cannot assign attribute on non-namespace object')\n        self.outdent()\n        self.writeline('%s[%r]' % (ref, node.attr))\n\n    def visit_Const(self, node, frame):\n        val = node.as_const(frame.eval_ctx)\n        if isinstance(val, float):\n            self.write(str(val))\n        else:\n            self.write(repr(val))\n\n    def visit_TemplateData(self, node, frame):\n        try:\n            self.write(repr(node.as_const(frame.eval_ctx)))\n        except nodes.Impossible:\n            self.write('(Markup if context.eval_ctx.autoescape else identity)(%r)'\n                       % node.data)\n","sourceCodeStart":1407,"sourceCodeEnd":1443,"githubUrl":"https://github.com/nodejs/node/blob/1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e/tools/inspector_protocol/jinja2/compiler.py#L1407-L1443","documentation":"Compiled-in runtime guard emitted by visit_NSRef when a template uses namespace attribute assignment (`{% set ns.foo = ... %}`) but the target is not a Jinja2 Namespace object at render time. NSRef nodes are emitted for `set x.y = value`; before performing the assignment the generated code asserts isinstance(ref, Namespace).","triggerScenarios":"Writing `{% set myvar.attr = 1 %}` where myvar was never initialized as a Namespace (it is a plain dict, a string, None, or undefined); shadowing a namespace variable with a non-namespace value partway through a template.","commonSituations":"Forgetting the `{% set ns = namespace() %}` initialization before `{% set ns.counter = 0 %}`; expecting dicts to support attribute assignment; using namespace mutation to carry state across loop iterations but reassigning ns to something else first.","solutions":["Initialize with `{% set ns = namespace(...) %}` before any `{% set ns.x = ... %}`.","If you intended a dict, use bracket access (`{% set _ = mydict.update(...) %}`) rather than attribute-set syntax.","Make sure the name used on the left of the dot is the same one bound to namespace()."],"exampleFix":"{# before #}\n{% set item.count = item.count + 1 %}\n{# after #}\n{% set item = namespace(count=0) %}\n{% set item.count = item.count + 1 %}","handlingStrategy":"validation","validationCode":"from jinja2 import Namespace\ndef ensure_namespace(var):\n    return var if isinstance(var, Namespace) else Namespace()","typeGuard":"from jinja2 import Namespace\ndef is_namespace(v) -> bool:\n    return isinstance(v, Namespace)","tryCatchPattern":null,"preventionTips":["Always initialize `{% set ns = namespace(...) %}` before `set ns.x = ...`.","Do not reuse a namespace name for a non-namespace value mid-template.","Use dicts with bracket access if you did not mean attribute assignment."],"tags":["jinja2","namespace","template","set"],"backgroundTag":null,"analyzedSha":"1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e","analyzedAt":"2026-08-13T00:53:24.642Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}