yewstack/yew · error

could not set property

Error message

could not set property

What it means

When a value is applied as a DOM property (packages/yew/src/dom_bundle/btag/attributes.rs:179), Yew uses js_sys::Reflect::set and unwraps with .expect("could not set property"). Reflect::set throws a TypeError when the target property is an accessor without a setter (getter-only like dataset, classList, isContentEditable) or non-writable/non-configurable, or when the property's own setter throws for the supplied value (e.g. an invalid value passed to a validating setter).

Source

Thrown at packages/yew/src/dom_bundle/btag/attributes.rs:179

            }
        }

        // Remove missing
        for (k, old_value) in old.iter() {
            if !new.contains_key(k) {
                Self::remove(el, k, old_value);
            }
        }
    }

    fn set(el: &Element, key: &str, value: &AttributeOrProperty) {
        match value {
            AttributeOrProperty::Attribute(value) => el
                .set_attribute(intern(key), value)
                .expect("invalid attribute key"),
            AttributeOrProperty::Property(value) => {
                let key = JsValue::from_str(key);
                js_sys::Reflect::set(el.as_ref(), &key, value).expect("could not set property");
            }
        }
    }

    /// Applies a value during hydration.
    ///
    /// Hydration assumes the DOM already matches the server-rendered HTML, so
    /// attributes are left untouched: re-writing them would needlessly trigger
    /// side effects. In debug builds we only assert that the existing attribute
    /// matches the expected value. Properties are not reflected in the HTML, so
    /// they are always set.
    #[cfg(feature = "hydration")]
    fn hydrate_set(el: &Element, key: &str, value: &AttributeOrProperty) {
        match value {
            AttributeOrProperty::Attribute(value) => {
                debug_assert_eq!(
                    el.get_attribute(key).as_deref(),
                    Some(value.as_ref()),

View on GitHub (pinned to 0e4a05472f)

Solutions

  1. Use the proper Yew API for the target: classes for class lists, attributes or listeners syntax for dataset-style data instead of property assignment
  2. Check the property is writable (has a setter) before assigning: js_sys::Reflect::get_own_property_descriptor or a quick manual check against a known getter-only list
  3. Ensure the value type matches what the DOM setter expects (bool vs string for checked/disabled style properties)

Example fix

// before
html! { <div dataset={some_map} /> }  // dataset is getter-only

// after
html! { <div data-role={"panel"} /> }  // set as attributes instead
Defensive patterns

Strategy: validation

Validate before calling

// allowlist writable properties before assigning them dynamically
const WRITABLE_PROPS: &[&str] = &["value", "checked", "href", "selected", "disabled", "innerHTML"];
fn is_writable_prop(name: &str) -> bool { WRITABLE_PROPS.contains(&name) }

if is_writable_prop(&key) { /* set property */ } else { /* set as attribute instead */ }

Type guard

fn is_getter_only_dom_prop(name: &str) -> bool { matches!(name, "dataset" | "classList" | "isContentEditable" | "style" ) }

Prevention

When it happens

Trigger: Setting a getter-only DOM property (dataset, classList, isContentEditable) through Yew property syntax; assigning a value the browser setter rejects, such as a malformed value to a property whose setter validates; setting a property on a frozen or non-configurable target element.

Common situations: Trying to bind classList/dataset as if they were settable properties instead of using classes!/attribute syntax; passing wrong-typed values to typed setters; plugins or tests freezing DOM objects before Yew patches attributes.

Related errors


AI-assisted analysis of yewstack/yew@0e4a05472f (2026-08-22). Data as JSON: /api/errors/6dafc5a2301b2277. Report an issue: GitHub.