oracle/graal · info · UnsupportedOperationException

putMember() not supported.

Error message

putMember() not supported.

What it means

UnsupportedOperationException from the read-only ProxyObject exposed by EspressoExternalHostProxies: putMember(key, value) throws because the proxy wraps an immutable Map.copyOf method map — the proxy's members are the host object's methods, not writable properties. Writes through this mirror have no backing store, so the operation is explicitly refused instead of being silently dropped.

Source

Thrown at espresso-compiler-stub/src/com.oracle.truffle.espresso.vmaccess/src/com/oracle/truffle/espresso/vmaccess/EspressoExternalHostProxies.java:386

                    public void set(long index, Value value) {
                        throw new UnsupportedOperationException("set() not supported.");
                    }

                    @Override
                    public long getSize() {
                        return keys.length;
                    }
                };
            }

            @Override
            public boolean hasMember(String key) {
                return map.containsKey(key);
            }

            @Override
            public void putMember(String key, Value value) {
                throw new UnsupportedOperationException("putMember() not supported.");
            }
        };
        Value computeMethodMapMirror = access.com_oracle_truffle_espresso_vmaccess_guest_GuestHostProxyHandler_computeMethodMap.getMirror();
        Value guestClass = guestType.getMetaObject().getMember("class");
        return computeMethodMapMirror.execute(guestClass, invocables);
    }

    private Map<String, ProxyExecutable> computeMethodMap(Class<?> hostClass, EspressoExternalResolvedInstanceType guestType) {
        Map<String, ProxyExecutable> map = new HashMap<>();
        Set<EspressoExternalResolvedInstanceType> seen = new HashSet<>();
        addMethods(hostClass, guestType, map, seen);
        return Map.copyOf(map);
    }

    private void addMethods(Class<?> hostClass, EspressoExternalResolvedInstanceType guestType, Map<String, ProxyExecutable> map, Set<EspressoExternalResolvedInstanceType> seen) {
        assert guestType.isInterface();
        if (!seen.add(guestType)) {
            return;

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Use member invocation (call the methods) instead of assignment; the mirror only dispatches methods.
  2. To expose writable state, add real setter methods to the host class — they appear as invocable members.
  3. Handle UnsupportedOperationException in the guest interop layer as 'member is not writable' (Truffle also exposes Member.isWritable, which already reports false here).
  4. Check Member.isWritable(key) before writeMember if the guest runtime supports the interop metadata API.

Example fix

// before (guest JS)
hostProxy.counter = 42; // putMember -> UnsupportedOperationException

// after (host adds a setter; guest calls it)
// host: public void setCounter(int v) { this.counter = v; }
hostProxy.setCounter(42);
Defensive patterns

Strategy: validation

Validate before calling

// interop caller: use member metadata before writeMember
if (proxy.getMemberKeys().contains(key) && proxy.getMember(key).isWritable()) {
    proxy.putMember(key, value);
} else {
    throw new UnsupportedOperationException("member not writable: " + key);
}

Try / catch

try { proxy.putMember(key, value); } catch (UnsupportedOperationException e) { /* method-map mirror is read-only: expose a setter method instead */ }

Prevention

When it happens

Trigger: Guest language code executing a property assignment (JS: hostProxy.foo = bar, or interop writeMember) on a host object exposed through the external host proxy mechanism.

Common situations: Guest scripts accustomed to polyglot Value objects that do allow member writes; debuggers/REPLs attempting to set fields on the mirror; mistaking the method-map mirror for a property bag.

Related errors


AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14). Data as JSON: /api/errors/1f153e32d02f73e7. Report an issue: GitHub.