appsmithorg/appsmith · error · ActionCalledInSyncFieldError
Please remove any direct/indirect references to {{actionName
Error message
Please remove any direct/indirect references to {{actionName}} and try again. Data fields cannot execute framework actions. What it means
Thrown by the isAsyncGuard wrapping every framework action exposed to the evaluation worker (e.g. showAlert, navigateTo, storeValue, setInterval/setTimeout overrides, geolocation, and setter methods wired through getFnWithGuards). Appsmith classifies bindings into data fields (self.$isDataField === true: properties that merely store data, such as Input.defaultText, Table.tableData, or a plain JS object property) and action fields (onClick, onRowSelect, JS object functions). When an action-wrapped function is invoked while $isDataField is true, the guard sets self.$isAsync = true and throws ActionCalledInSyncFieldError(actionName), whose message substitutes {{actionName}} with fnName + '()'. The rule exists because data fields are evaluated synchronously and must stay free of side effects.
Source
Thrown at app/client/src/workers/Evaluation/fns/utils/fnGuard.ts:37
// eslint-disable-next-line @typescript-eslint/no-explicit-any
value: function (...args: any[]) {
const fnWithGuards = getFnWithGuards(fn, fnName, fnGuards);
return fnWithGuards(...args);
},
enumerable: false,
writable: true,
configurable: true,
});
}
export function isAsyncGuard<P extends ReadonlyArray<unknown>>(
fn: (...args: P) => unknown,
fnName: string,
) {
if (self.$isDataField) {
self["$isAsync"] = true;
throw new ActionCalledInSyncFieldError(fnName);
}
}
export function getFnWithGuards(
// TODO: Fix this the next time the file is edited
// eslint-disable-next-line @typescript-eslint/no-explicit-any
fn: (...args: any[]) => unknown,
fnName: string,
fnGuards: FnGuard[],
) {
// TODO: Fix this the next time the file is edited
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return (...args: any[]) => {
for (const guard of fnGuards) {
guard(fn, fnName);
}
return fn(...args);View on GitHub (pinned to 8cd9021c24)
Solutions
- Move the action call into an action/event field (the widget's onClick/onSuccess, or a JS object function) rather than a data field.
- If you need the action driven by a value change, bind the action field to run on the onChange event of the source widget instead of computing it inline in the data field.
- Replace side-effecting logic in a data field with a pure expression; store the result of async work via storeValue from an action and read that stored value in the data field.
- Search the data field binding for the named action (the message includes actionName) and remove every direct/indirect reference to it.
Example fix
// before (Input1.defaultText - a DATA field)
"Welcome " + (function(){ appsmith.actions.showAlert('set'); return user.name })()
// after
// Input1.defaultText (data field, pure):
"Welcome " + user.name
// Input1.onTextChanged (action field):
appsmith.actions.showAlert('name set') Defensive patterns
Strategy: validation
Validate before calling
// Structural validation: never call action functions inside a data field. // Data fields (self.$isDataField === true) include widget value/default properties // and plain JS-object properties. Action functions (wrapped by isAsyncGuard) are // showAlert, navigateTo, storeValue, setInterval/setTimeout overrides, geolocation, // and setter methods. // // Rule: if a binding only STORES data, keep it a pure expression; if it must DO // something, move it into an action/event field (onClick, onSuccess, a JS fn).
Type guard
// There is no safe runtime call to make here: the guard fires at invocation. // The 'type guard' is structural - know which binding is a data field vs action: const ACTION_NAMES = new Set([ 'showAlert', 'navigateTo', 'storeValue', 'removeValue', 'clearStore', 'download', 'copyToClipboard', 'resetWidget', 'setInterval', 'setTimeout', 'clearInterval', 'clearTimeout', ]); const isFrameworkAction = (name) => ACTION_NAMES.has(name); // Never reference isFrameworkAction(name) inside a data field binding.
Try / catch
// try/catch will NOT make an action legal in a data field - it only suppresses
// the guard. The correct pattern is to relocate the call:
//
// BAD (data field Input1.defaultText):
// (appsmith.actions.showAlert('x'), user.name)
// GOOD:
// Input1.defaultText -> user.name
// Input1.onTextChanged -> appsmith.actions.showAlert('x') Prevention
- Treat any binding that stores a value (defaultText, text, tableData, options, sourceData, plain JS-object props) as a data field: pure expressions only.
- Put side-effecting calls only in event/action fields: onClick, onRowSelect, onSuccess, onError, onTextChanged, or a JS object function.
- If async work must feed a data field, run it in an action that calls storeValue, then read that stored value in the data field.
- When you see the message, search the named binding for actionName (with '()') and remove every direct and indirect reference.
When it happens
Trigger: Writing appsmith.actions.showAlert('hi') or navigateTo(url) inside a data property such as Input1.defaultText, Table1.tableData, or a non-function property of a JS object; calling setInterval/setTimeout or appsmith.geolocation.getCurrentPosition() in a data field; indirectly referencing an action inside an IIFE or helper that runs during data-field evaluation.
Common situations: New users assuming every binding can trigger actions; refactoring an onClick handler into a default value; calling a JS object function that internally invokes an action, from within a data field; copy-pasting a workflow snippet into the wrong property.
Related errors
- Found a Promise() during evaluation. Data fields cannot exec
- The ${path} path must start with 'https://'.
- Please enter a target origin URL.
- Failed to load JS libraries
- onModelChange expects a function as parameter
AI-assisted analysis of appsmithorg/appsmith@8cd9021c24 (2026-08-12).
Data as JSON: /api/errors/a15c71ac2d2b88be.
Report an issue: GitHub.