{"record":{"id":"5ba38bc77b3b43ea","repo":"windmill-labs/windmill","slug":"cannot-set-value-on-objects-that-are-neither-the-g","errorCode":null,"errorMessage":"Cannot set value on objects that are neither the global state or a container group field","messagePattern":"Cannot set value on objects that are neither the global state or a container group field","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"frontend/src/lib/components/apps/components/helpers/eval.ts","lineNumber":146,"sourceCode":"\t\t\tsetGroupValue?: (key: string, value: any) => void\n\t\t\tsendMessage?: (message: string) => void\n\t\t}\n\t>,\n\tworldStore: World | undefined,\n\trunnableComponents: Record<string, { cb?: (() => void)[] }>,\n\tnoReturn: boolean,\n\tgroupContextId: string | undefined,\n\tglobalRecomputeFunction: ((excludeIds?: string) => void) | undefined\n) {\n\tconst createProxy = (name: string, obj: any) => {\n\t\t// console.log('Creating proxy', name, obj)\n\t\tif (obj != null && obj != undefined && typeof obj == 'object') {\n\t\t\tif (name == 'group' && groupContextId) {\n\t\t\t\treturn createGroupProxy(groupContextId, obj)\n\t\t\t}\n\t\t\treturn new Proxy(obj, {\n\t\t\t\tset(target, key, value) {\n\t\t\t\t\tif (name != 'state') {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t'Cannot set value on objects that are neither the global state or a container group field'\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t\tif (typeof key !== 'string') {\n\t\t\t\t\t\tthrow new Error('Invalid key')\n\t\t\t\t\t}\n\t\t\t\t\ttarget[key] = value\n\t\t\t\t\tlet o = worldStore?.newOutput(name, key, value)\n\t\t\t\t\to?.set(value, true)\n\n\t\t\t\t\treturn true\n\t\t\t\t},\n\t\t\t\tget(obj, prop) {\n\t\t\t\t\tif (name != 'state' && prop == 'group') {\n\t\t\t\t\t\treturn createGroupProxy(name, obj[prop])\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn obj[prop]","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/frontend/src/lib/components/apps/components/helpers/eval.ts#L128-L164","documentation":"In Windmill app frontend expressions, the eval sandbox wraps context objects in a Proxy whose set trap only allows writes to the global 'state' object (or to a container 'group' field when a group context exists). Writing to any other proxied object (e.g. results, inputs, UI component outputs) throws this error. It exists because only state mutations are tracked and allowed to trigger recomputes.","triggerScenarios":"Inside an app frontend expression/event handler, assigning to a non-state context object, e.g. `results.myStep = ...`, `inputs.x = 1`, `ui.button.disabled = true` at top level, or `myComponent.someProp = v` when the component is not exposed as a container group field with a groupContextId.","commonSituations":"Trying to save computed data back onto step results instead of state; mutating a component's returned object from a button onClick handler; copy-pasting `results.foo = bar` patterns from scripts into app expressions; group writes attempted without a container group context (groupContextId undefined).","solutions":["Assign to the global state instead: `state.myKey = value`, then reference state.myKey elsewhere","If inside a container component, write via the group proxy: `group.myKey = value` (only valid within a container group context)","To mutate a component programmatically, use its control API (e.g. controlComponents setValue/setTab) rather than assigning to the result object","For persisted values across runs, use a state variable or a resource, not step results"],"exampleFix":"// before (onClick handler)\nresults.total = inputs.a + inputs.b\n// after\nstate.total = inputs.a + inputs.b","handlingStrategy":"try-catch","validationCode":"// before writing in an app expression, ensure the target is state (or group inside a container)\nif (targetName !== 'state') {\n  // redirect the write to state instead\n  state[myKey] = value\n}","typeGuard":null,"tryCatchPattern":"try {\n  results.total = inputs.a + inputs.b\n} catch (e) {\n  if (String(e.message).includes('neither the global state')) {\n    state.total = inputs.a + inputs.b // fall back to the sanctioned target\n  } else throw e\n}","preventionTips":["Only ever assign to `state.<key>` (or `group.<key>` inside a container component) in app expressions","Treat step results, inputs and component outputs as read-only in the frontend sandbox","Use component control APIs (setValue, setTab, openModal, ...) for programmatic component changes","Remember group writes require a container group context (groupContextId) to be active"],"tags":["windmill-apps","eval","proxy","state-mutation","frontend"],"backgroundTag":"read-only-context-mutation","analyzedSha":"e474e8803ce2ff5c2df09a58dab51d45f5c922ca","analyzedAt":"2026-09-03T12:38:19.024Z","contentChangedAt":"2026-09-03T12:38:19.024Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}