windmill-labs/windmill · error
Invalid key
Error message
Invalid key
What it means
The same eval sandbox Proxy for the global state validates that every assigned key is a string before writing it and syncing the value into the World store. Symbol or non-string keys (e.g. from programmatic/spread logic, Symbol.iterator, or obfuscated expression code) throw 'Invalid key'.
Source
Thrown at frontend/src/lib/components/apps/components/helpers/eval.ts:151
runnableComponents: Record<string, { cb?: (() => void)[] }>,
noReturn: boolean,
groupContextId: string | undefined,
globalRecomputeFunction: ((excludeIds?: string) => void) | undefined
) {
const createProxy = (name: string, obj: any) => {
// console.log('Creating proxy', name, obj)
if (obj != null && obj != undefined && typeof obj == 'object') {
if (name == 'group' && groupContextId) {
return createGroupProxy(groupContextId, obj)
}
return new Proxy(obj, {
set(target, key, value) {
if (name != 'state') {
throw new Error(
'Cannot set value on objects that are neither the global state or a container group field'
)
}
if (typeof key !== 'string') {
throw new Error('Invalid key')
}
target[key] = value
let o = worldStore?.newOutput(name, key, value)
o?.set(value, true)
return true
},
get(obj, prop) {
if (name != 'state' && prop == 'group') {
return createGroupProxy(name, obj[prop])
} else {
return obj[prop]
}
}
})
} else {
return objView on GitHub (pinned to e474e8803c)
Solutions
- Use string keys only: ensure the key expression evaluates to a string, e.g. `state[String(key)] = value`
- Check for accidental symbol-key assignment (Symbol.iterator, Symbol.asyncIterator) — spread those objects explicitly instead
- If copying objects, assign the whole object once (`state.items = obj`) rather than copying its keys individually
Example fix
// before
state[myKey] = value // myKey may be a symbol
// after
if (typeof myKey !== 'string') throw new Error('state keys must be strings')
state[myKey] = value Defensive patterns
Strategy: validation
Validate before calling
if (typeof key !== 'string') {
throw new Error(`state keys must be strings, got ${typeof key}`)
}
state[key] = value Type guard
function isStringKey(key: PropertyKey): key is string {
return typeof key === 'string'
} Try / catch
try {
state[key] = value
} catch (e) {
if (e.message === 'Invalid key') {
state[String(key)] = value
} else throw e
} Prevention
- Never use Symbol or non-string keys when writing to app state
- Avoid spreading objects with symbol keys directly onto the state proxy
- Coerce dynamic keys with String(key) or template literals before assignment
- Keep state writes simple and literal in expression handlers to stay within the sandbox's assumptions
When it happens
Trigger: Assigning a computed property with a Symbol key to state inside an app expression, e.g. `state[symbolKey] = v`, or library/user code that runs Object.assign-like logic with symbol keys against the state proxy, or numeric keys coerced from exotic paths.
Common situations: Using spread or utility functions that copy symbols onto state; defining custom Symbol.toPrimitive/iterator interactions on objects assigned into state; writing expression code with dynamic bracket access where the key evaluates to a symbol.
Related errors
- Cannot set value on objects that are neither the global stat
- No model selected
- No workspace available
- Unimplemented case
- Unsupported database type: ${dbType}
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/bf6f2d7b6f74ddb4.
Report an issue: GitHub.