HelloZeroNet/ZeroNet · error · Error

"class" property may not be updated. Use the "classes" prope

Error message

"class" property may not be updated. Use the "classes" property for conditional css classes.

What it means

After initial render, maquette forbids changing the `class` string property on updates; static class changes would require patching in ways maquette does not reconcile. Conditional classes must be expressed with the `classes` object, whose boolean entries maquette adds/removes from the DOM classList on each render.

Source

Thrown at plugins/UiConfig/media/js/all.js:378

                }
            }
        }
    };
    var updateProperties = function (domNode, previousProperties, properties, projectionOptions) {
        if (!properties) {
            return;
        }
        var propertiesUpdated = false;
        var propNames = Object.keys(properties);
        var propCount = propNames.length;
        for (var i = 0; i < propCount; i++) {
            var propName = propNames[i];
            // assuming that properties will be nullified instead of missing is by design
            var propValue = properties[propName];
            var previousValue = previousProperties[propName];
            if (propName === 'class') {
                if (previousValue !== propValue) {
                    throw new Error('"class" property may not be updated. Use the "classes" property for conditional css classes.');
                }
            } else if (propName === 'classes') {
                var classList = domNode.classList;
                var classNames = Object.keys(propValue);
                var classNameCount = classNames.length;
                for (var j = 0; j < classNameCount; j++) {
                    var className = classNames[j];
                    var on = !!propValue[className];
                    var previousOn = !!previousValue[className];
                    if (on === previousOn) {
                        continue;
                    }
                    propertiesUpdated = true;
                    if (on) {
                        classList.add(className);
                    } else {
                        classList.remove(className);
                    }

View on GitHub (pinned to 454c0b2e7e)

Solutions

  1. Move conditional classes into `classes`: { classes: { 'is-active': isActive } } and keep `class` constant (or omit it).
  2. If the base class never changes, keep it in `class` and only vary `classes`.
  3. Restructure so each distinct class combination is represented by different vnode structure/keys if truly dynamic static classes are needed.
  4. As a last resort, manage the class directly via a custom afterCreate/afterUpdate handler, but this bypasses the VDOM diff.

Example fix

// before
h('div', { class: isActive ? 'card active' : 'card' })
// after
h('div', { class: 'card', classes: { active: isActive } })
Defensive patterns

Strategy: validation

Validate before calling

function assertClassStable(prevProps, nextProps) {
  if (prevProps && nextProps && prevProps.class !== nextProps.class) {
    throw new Error('Move conditional classes into the classes object');
  }
}

Type guard

function classIsConditionalSafe(prev, next) {
  return prev == null || next == null || prev.class === next.class;
}

Try / catch

try {
  projection.update(vnode);
} catch (e) {
  if (e.message.indexOf('"class" property may not be updated') !== -1) {
    console.error('Use classes: { name: bool } for conditional classes');
  }
  throw e;
}

Prevention

When it happens

Trigger: A subsequent projection.update(updatedVnode) (or projector render pass) supplies a vnode whose `class` property value differs from the previous render's value.

Common situations: Building dynamic class strings with template literals or conditionals (class: isActive ? 'a' : 'b'); toggling state classes on re-render; porting code that assumed class behaves like other attributes.

Related errors


AI-assisted analysis of HelloZeroNet/ZeroNet@454c0b2e7e (2026-09-02). Data as JSON: /api/errors/196902b50f2f4018. Report an issue: GitHub.