karatelabs/karate · error · JsErrorException (typeError)

cannot set

Error message

cannot set '${name}'

What it means

A TypeError raised when a property write is routed to the external Java bridge (context.root.bridge) and the bridge call throws — Karate logs the underlying bridge error and rethrows as 'cannot set <name>'. The same message is also thrown in the final else branch when the target object type supports no property write at all. Effectively: the engine could not assign this property on this object.

Solutions

  1. Check the log line 'external bridge error: ...' for the real underlying exception and fix that root cause (type mismatch, exception in setter).
  2. Verify the property exists and is writable on the target Java object; use a setter-compatible name and type.
  3. Coerce the value to the expected Java type before assigning (e.g. wrap numbers/strings appropriately).
  4. If the object genuinely doesn't support writes, store the value in a JS variable or Map instead of the host object.

Example fix

// before
* eval javaObj.count = 'abc'  // bridge setter expects int -> throws
// after
* eval javaObj.count = 5
Defensive patterns

Strategy: try-catch

Validate before calling

// Java side: validate writability before the call
if (bean.getProperty(name) == null && !bean.hasWritableProperty(name)) throw new IllegalStateException(name + " not writable");

Try / catch

* eval
  try { karate.set('javaObj.field', v) } catch (e) { karate.log('bridge set failed: ' + e) }

Prevention

When it happens

Trigger: Setting a property on a bridged Java/external object (via the JS<->Java bridge) where setProperty fails (wrong type, read-only field, exception inside the Java setter), or assigning to a value whose type has no setter support (e.g. a primitive or immutable value in a `super`/receiver path).

Common situations: Karate UI/API integrations writing to Java objects from JS, typed value mismatches (assigning a string to an int-typed bean property), attempting to mutate a read-only or frozen host object.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12). Data as JSON: /api/errors/afb3c2df33db755d. Report an issue: GitHub.

Appendix: source

Thrown at karate-js/src/main/java/io/karatelabs/js/PropertyAccess.java:1210

            objectLike.putMember(name, value, context, context.strict);
            firePropertySet(context, name, value, oldValue, object, trackingNode);
        } else if (object instanceof Map) {
            Map<String, Object> map = (Map<String, Object>) object;
            Object oldValue = map.get(name);
            map.put(name, value);
            firePropertySet(context, name, value, oldValue, object, trackingNode);
        } else if (context.root.bridge != null) {
            try {
                if (object instanceof ExternalAccess ja) {
                    ja.setProperty(name, value);
                } else {
                    ExternalAccess ja = context.root.bridge.forInstance(object);
                    ja.setProperty(name, value);
                }
                firePropertySet(context, name, value, null, object, trackingNode);
            } catch (Exception e) {
                logger.error("external bridge error: {}", e.getMessage());
                throw JsErrorException.typeError("cannot set '" + name + "'");
            }
        } else {
            throw JsErrorException.typeError("cannot set '" + name + "'");
        }
    }

    private static void firePropertySet(CoreContext context, String name, Object value, Object oldValue, Object target, Node node) {
        if (context.root.listener != null) {
            context.root.listener.onBind(BindEvent.propertySet(name, value, oldValue, target, context, node));
        }
    }

    private static Object postIncDecByIndex(Object object, Object index, boolean isIncrement, CoreContext context) {
        if (index instanceof Number n) {
            int i = denseIndex(n);
            if (object instanceof List && i >= 0) {
                List<Object> list = (List<Object>) object;
                Object oldValue = i < list.size() ? list.get(i) : Terms.UNDEFINED;

View on GitHub (pinned to a22eb90246)