danny-avila/LibreChat · error · Error
invalid_action_error
invalid_action_error
Error message
{"type":"invalid_action_error"} What it means
Thrown by the Assistants-API action-tool path in ToolService when createActionTool(...) returns a falsy value for a required action. The thrown payload is a JSON string {"type":"invalid_action_error"} (ErrorTypes.INVALID_ACTION) so downstream handlers can detect it by type. A null tool means the action could not be constructed — typically missing metadata, failed OAuth decryption, or SSRF/address-policy rejection.
Source
Thrown at api/server/services/ToolService.js:466
// We've already decrypted the metadata, so we can pass it directly
const _allowedDomains = appConfig?.actions?.allowedDomains;
const _allowedAddresses = appConfig?.actions?.allowedAddresses;
tool = await createActionTool({
userId: client.req.user.id,
res: client.res,
action,
requestBuilder,
// Note: intentionally not passing zodSchema, name, and description for assistants API
encrypted, // Pass the encrypted values for OAuth flow
useSSRFProtection: !Array.isArray(_allowedDomains) || _allowedDomains.length === 0,
allowedAddresses: _allowedAddresses,
});
if (!tool) {
logger.warn(
`Invalid action: user: ${client.req.user.id} | thread_id: ${requiredActions[0].thread_id} | run_id: ${requiredActions[0].run_id} | toolName: ${currentAction.tool}`,
);
throw new Error(`{"type":"${ErrorTypes.INVALID_ACTION}"}`);
}
isActionTool = !!tool;
ActionToolMap[currentAction.tool] = tool;
}
if (currentAction.tool === 'calculator') {
currentAction.toolInput = currentAction.toolInput.input;
}
const handleToolError = (error) => {
logger.error(
`tool_call_id: ${currentAction.toolCallId} | Error processing tool ${currentAction.tool}`,
error,
);
return {
tool_call_id: currentAction.toolCallId,
output: `Error processing tool ${currentAction.tool}: ${redactMessage(error.message, 256)}`,
};View on GitHub (pinned to 5ff282f900)
Solutions
- Re-open the action configuration in the UI and confirm all required fields (endpoint, auth, schema) are present and saved.
- If using OAuth, complete the OAuth flow again so fresh encrypted values are stored.
- Review appConfig.actions.allowedDomains/allowedAddresses and add the action's domain, or disable useSSRFProtection intentionally by configuring allowedDomains.
- Check the preceding logger.warn line which records user/thread/run/toolName — it identifies exactly which action failed to build.
Example fix
// before (no guard, raw error bubbles to the run)
const tool = await createActionTool({ ... });
// after (caller)
if (!tool) {
return { output: `Action '${currentAction.tool}' is misconfigured. Please re-authorize it.` };
} Defensive patterns
Strategy: try-catch
Validate before calling
const entry = actionSetsData.get(normalizeActionToolName(currentAction.tool));
if (!entry) {
return { output: `Action '${currentAction.tool}' is not available.` };
} Type guard
const isActionConfigured = (actionSetsData, tool) => actionSetsData.has(normalizeActionToolName(tool));
Try / catch
try {
// ... build and run action tool ...
} catch (err) {
if (err.message.includes('invalid_action_error')) {
return { output: `Action '${currentAction.tool}' is misconfigured. Re-authorize it.` };
}
throw err;
} Prevention
- Keep action definitions and their OAuth credentials current.
- Configure appConfig.actions.allowedDomains/allowedAddresses deliberately.
- Audit the warn log line naming user/thread/run/toolName to catch misconfigurations early.
When it happens
Trigger: An assistant run submits a required_action for a tool whose action definition was deleted or never fully configured; the action's encrypted OAuth values cannot be decrypted; useSSRFProtection blocked the action's domain because allowedDomains is empty and the action URL is non-allowlisted; the requestBuilder or action payload is incomplete.
Common situations: User deleted an action after the run started; OAuth credentials expired and re-encryption produced an unreadable value; an admin tightened actions.allowedDomains/allowedAddresses so a previously-working action is now blocked.
Related errors
- Trouble deleting Assistant Actions for Assistant ID: ${assis
- Missing AZURE_AI_SEARCH_SERVICE_ENDPOINT, AZURE_AI_SEARCH_IN
- Missing DALLE_API_KEY environment variable.
- Missing FLUX_API_KEY environment variable.
- Gemini Image Generation requires one of: user-provided API k
AI-assisted analysis of danny-avila/LibreChat@5ff282f900 (2026-08-12).
Data as JSON: /api/errors/bca72236fd0ac109.
Report an issue: GitHub.