You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A legacy @rx.memo (the old custom-component decorator) whose parameters are unannotated compiled fine on 0.9.3 and raises UntypedVarError at compile time on 0.9.4.
The memo refactor in 0.9.4 (de6393e9 / #6517, softened by baf10e65 / #6598) changed how a memo parameter's Vartype is derived:
0.9.3 typed each prop placeholder from the call-site value — CustomComponent.get_prop_vars():
0.9.4 types it from the parameter annotation — _var_placeholder() → _annotation_inner_type(), and in _analyze_params() a missing annotation becomes Var[Any]:
So an unannotated param that used to be typed from what the caller passed is now an untyped Var[Any], and any operation on it fails. (#6598 added bare-type coercion + a deprecation warning, so param: dict works — only the missing-annotation case still degrades to Var[Any].)
UntypedVarError: Cannot access the item 'name' on untyped var 'userRxMemo'
of type 'typing.Any'. You can call the var's .to(desired_type) method to
convert it to the desired type.
The surface error depends on what the body does with the param (all compile on 0.9.3):
memo body on an unannotated param
0.9.4 result
user["x"] / user.x
UntypedVarError
name.upper(), .lower(), .split(), .startswith()
UntypedVarError
rx.foreach(items, ...)
ForeachVarError
"Hello " + name
TypeError: can only concatenate str (not "Var") to str
rx.input(on_change=handler_param)
ValueError: Invalid event chain ... of type typing.Any
Expected behavior
Either keep the 0.9.3 behavior (type an unannotated / Var[Any] param from the bound call-site value via .guess_type()), or treat a missing annotation as the loud, eager deprecation/error case rather than a silent Var[Any] that explodes downstream with a confusing message.
Specifics (please complete the following information):
Python Version: reproduced on 3.10 and 3.14
Reflex Version: regression introduced in 0.9.4 (works on 0.9.3)
OS: any (reproduced on Linux; not OS-specific — see below)
Additional context
Verified head-to-head on clean PyPI installs:
Python 3.10
Python 3.14
0.9.3
✅ compiles
✅ compiles
0.9.4
❌ UntypedVarError
❌ UntypedVarError
Workaround for users: annotate the param, e.g. user: rx.Var[dict] (or rx.RestProp, rx.Var[rx.Component] for children).
This was investigated alongside a telemetry spike in UntypedVarError, EventHandlerArgTypeMismatchError, and AttributeError on 0.9.4:
EventHandlerArgTypeMismatchError fires identically on 0.9.3 and 0.9.4 in every path tested (call_event_handler / _check_event_args_subclass_of_callback are unchanged between the tags) — not reproducible as a regression; likely secondary.
AttributeError: VarAttributeError is unchanged across versions; the only new AttributeError path is HybridProperty.__get__ (add hybrid_property #3806) — unconfirmed as a regression.
The "Linux" skew in telemetry is most likely a deployment/volume artifact (apps recompile at scale in Linux CI/Docker/prod, where memo bodies first evaluate), not an OS-specific code path. Suggest re-slicing telemetry by Python version and run vs export.
Distinct from #6599 (RestProp CSS props). A related secondary 0.9.4 regression: base props (class_name, style, id) on a @rx.memo without rx.RestProp now raise TypeError where 0.9.3 forwarded them.
Describe the bug
A legacy
@rx.memo(the old custom-component decorator) whose parameters are unannotated compiled fine on 0.9.3 and raisesUntypedVarErrorat compile time on 0.9.4.The memo refactor in 0.9.4 (
de6393e9/ #6517, softened bybaf10e65/ #6598) changed how a memo parameter'sVartype is derived:CustomComponent.get_prop_vars():_var_placeholder()→_annotation_inner_type(), and in_analyze_params()a missing annotation becomesVar[Any]:So an unannotated param that used to be typed from what the caller passed is now an untyped
Var[Any], and any operation on it fails. (#6598 added bare-type coercion + a deprecation warning, soparam: dictworks — only the missing-annotation case still degrades toVar[Any].)To Reproduce
reflex run(or evenindex().render()) raises:The surface error depends on what the body does with the param (all compile on 0.9.3):
user["x"]/user.xUntypedVarErrorname.upper(),.lower(),.split(),.startswith()UntypedVarErrorrx.foreach(items, ...)ForeachVarError"Hello " + nameTypeError: can only concatenate str (not "Var") to strrx.input(on_change=handler_param)ValueError: Invalid event chain ... of type typing.AnyExpected behavior
Either keep the 0.9.3 behavior (type an unannotated /
Var[Any]param from the bound call-site value via.guess_type()), or treat a missing annotation as the loud, eager deprecation/error case rather than a silentVar[Any]that explodes downstream with a confusing message.Specifics (please complete the following information):
Additional context
Verified head-to-head on clean PyPI installs:
UntypedVarErrorUntypedVarErrorWorkaround for users: annotate the param, e.g.
user: rx.Var[dict](orrx.RestProp,rx.Var[rx.Component]for children).This was investigated alongside a telemetry spike in
UntypedVarError,EventHandlerArgTypeMismatchError, andAttributeErroron 0.9.4:EventHandlerArgTypeMismatchErrorfires identically on 0.9.3 and 0.9.4 in every path tested (call_event_handler/_check_event_args_subclass_of_callbackare unchanged between the tags) — not reproducible as a regression; likely secondary.AttributeError:VarAttributeErroris unchanged across versions; the only newAttributeErrorpath isHybridProperty.__get__(add hybrid_property #3806) — unconfirmed as a regression.runvsexport.Distinct from #6599 (RestProp CSS props). A related secondary 0.9.4 regression: base props (
class_name,style,id) on a@rx.memowithoutrx.RestPropnow raiseTypeErrorwhere 0.9.3 forwarded them.