n8n-io/n8n · error · NodeOperationError
error?.description || error?.message
Error message
error?.description || error?.message
What it means
This is the dynamic description of a NodeOperationError thrown by the Guardrails process handler when an 'unexpectedError' guardrail result occurs and continueOnFail is false. The thrown error's message is the underlying reason/originalException object, and its description falls back to error?.description then error?.message. It surfaces a guardrail that rejected or reported executionFailed for a reason other than a normal tripwire.
Source
Thrown at packages/@n8n/nodes-langchain/nodes/Guardrails/actions/process.ts:70
const handleFailedResults = (results: GroupedGuardrailResults): GuardrailUserResult[] => {
const unexpectedError = results.failed.find(
(result) =>
result.status === 'rejected' ||
(result.status === 'fulfilled' && result.value.executionFailed),
);
if (results.failed.length && operation === 'sanitize') {
throw new NodeOperationError(this.getNode(), 'Failed to sanitize text', {
description: mapGuardrailErrorsToMessage(results.failed),
itemIndex,
});
}
if (unexpectedError && !this.continueOnFail()) {
const error =
unexpectedError.status === 'rejected'
? unexpectedError.reason
: unexpectedError.value.originalException;
throw new NodeOperationError(this.getNode(), error, {
description: error?.description || error?.message,
itemIndex,
});
}
return results.failed.map(mapGuardrailResultToUserResult);
};
const stageGuardrails: StageGuardRails = {
preflight: [],
input: [],
};
const checkModelAvailable = (model: BaseChatModel | null): model is BaseChatModel => {
if (!model) {
throw new NodeOperationError(this.getNode(), 'Chat Model is required');
}
return true;
};View on GitHub (pinned to 5ac6606e81)
Solutions
- Read the underlying error.message/description to identify whether it is a model/auth/network failure versus a guardrail logic failure.
- For transient model/API errors, retry the execution or fix credentials/connection for the upstream model.
- If the specific guardrail is non-essential, disable it or move it to a stage that tolerates failure.
- Enable 'Continue On Fail' on the node to let the workflow proceed and capture the failed item instead of aborting.
Defensive patterns
Strategy: try-catch
Try / catch
try {
await runGuardrails(...);
} catch (e) {
if (e instanceof NodeOperationError && e.description) {
// log description, decide retry vs fallback
}
} Prevention
- Stabilize upstream model connections to avoid executionFailed results.
- Enable Continue On Fail where partial results are acceptable.
- Log the underlying description to distinguish transient vs logic failures.
When it happens
Trigger: handleFailedResults() finds the first result with status === 'rejected' OR (fulfilled with value.executionFailed). With continueOnFail() false, it extracts the reason (rejected) or originalException (fulfilled) and throws NodeOperationError(node, error, { description }). Fires when a guardrail check promise rejects (network/model/runtime failure) or when a guardrail explicitly marks executionFailed.
Common situations: An LLM-backed guardrail whose model request fails (rate limit, bad credentials, timeout); a guardrail throwing on unexpected input shape; a guardrail dependency error; transient API errors surfacing through the guardrail runtime.
Related errors
- Failed to sanitize text
- error?.description || error?.message || 'Unknown error'
- Guardrail validation failed: ${error instanceof Error ? erro
- Request to Azure Blob storage failed: ${error.message}
- Request to S3 failed: ${error.message}
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/15c17868142d029c.
Report an issue: GitHub.