{"record":{"id":"1f153e32d02f73e7","repo":"oracle/graal","slug":"putmember-not-supported","errorCode":null,"errorMessage":"putMember() not supported.","messagePattern":"putMember\\(\\) not supported\\.","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"info","filePath":"espresso-compiler-stub/src/com.oracle.truffle.espresso.vmaccess/src/com/oracle/truffle/espresso/vmaccess/EspressoExternalHostProxies.java","lineNumber":386,"sourceCode":"                    public void set(long index, Value value) {\n                        throw new UnsupportedOperationException(\"set() not supported.\");\n                    }\n\n                    @Override\n                    public long getSize() {\n                        return keys.length;\n                    }\n                };\n            }\n\n            @Override\n            public boolean hasMember(String key) {\n                return map.containsKey(key);\n            }\n\n            @Override\n            public void putMember(String key, Value value) {\n                throw new UnsupportedOperationException(\"putMember() not supported.\");\n            }\n        };\n        Value computeMethodMapMirror = access.com_oracle_truffle_espresso_vmaccess_guest_GuestHostProxyHandler_computeMethodMap.getMirror();\n        Value guestClass = guestType.getMetaObject().getMember(\"class\");\n        return computeMethodMapMirror.execute(guestClass, invocables);\n    }\n\n    private Map<String, ProxyExecutable> computeMethodMap(Class<?> hostClass, EspressoExternalResolvedInstanceType guestType) {\n        Map<String, ProxyExecutable> map = new HashMap<>();\n        Set<EspressoExternalResolvedInstanceType> seen = new HashSet<>();\n        addMethods(hostClass, guestType, map, seen);\n        return Map.copyOf(map);\n    }\n\n    private void addMethods(Class<?> hostClass, EspressoExternalResolvedInstanceType guestType, Map<String, ProxyExecutable> map, Set<EspressoExternalResolvedInstanceType> seen) {\n        assert guestType.isInterface();\n        if (!seen.add(guestType)) {\n            return;","sourceCodeStart":368,"sourceCodeEnd":404,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/espresso-compiler-stub/src/com.oracle.truffle.espresso.vmaccess/src/com/oracle/truffle/espresso/vmaccess/EspressoExternalHostProxies.java#L368-L404","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Use member invocation (call the methods) instead of assignment; the mirror only dispatches methods.","To expose writable state, add real setter methods to the host class — they appear as invocable members.","Handle UnsupportedOperationException in the guest interop layer as 'member is not writable' (Truffle also exposes Member.isWritable, which already reports false here).","Check Member.isWritable(key) before writeMember if the guest runtime supports the interop metadata API."],"exampleFix":"// before (guest JS)\nhostProxy.counter = 42; // putMember -> UnsupportedOperationException\n\n// after (host adds a setter; guest calls it)\n// host: public void setCounter(int v) { this.counter = v; }\nhostProxy.setCounter(42);","handlingStrategy":"validation","validationCode":"// interop caller: use member metadata before writeMember\nif (proxy.getMemberKeys().contains(key) && proxy.getMember(key).isWritable()) {\n    proxy.putMember(key, value);\n} else {\n    throw new UnsupportedOperationException(\"member not writable: \" + key);\n}","typeGuard":null,"tryCatchPattern":"try { proxy.putMember(key, value); } catch (UnsupportedOperationException e) { /* method-map mirror is read-only: expose a setter method instead */ }","preventionTips":["Expose setters as methods on the host class instead of expecting property writes on the mirror.","Query Member.isWritable before writeMember in guest tooling.","Remember the external host proxy mirrors methods (Map.copyOf), not mutable fields."],"tags":["polyglot","truffle","proxy-object","read-only","unsupported-operation"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}