n8n-io/n8n · error · GuardrailError

error?.description || error?.message || 'Unknown error'

Error message

error?.description || error?.message || 'Unknown error'

What it means

This is the fallback message inside GuardrailError thrown by wrapInGuardrailError() in the Guardrails base helper. It catches any rejection from a guardrail check promise and re-throws a GuardrailError whose message is error?.description || error?.message || 'Unknown error' and whose description is error?.description. It normalizes arbitrary thrown values into the GuardrailError shape so stage aggregation can group them.

Source

Thrown at packages/@n8n/nodes-langchain/nodes/Guardrails/helpers/base.ts:18

import {
	type GuardrailResult,
	GuardrailError,
	type GroupedGuardrailResults,
	type StageGuardRails,
} from '../actions/types';

type RunStageGuardrailsOptions = {
	stageGuardrails: StageGuardRails;
	stage: keyof StageGuardRails;
	inputText: string;
	failOnlyOnErrors?: boolean;
};

// eslint-disable-next-line @typescript-eslint/promise-function-async
const wrapInGuardrailError = (guardrailName: string, promise: Promise<GuardrailResult>) => {
	return promise.catch((error) => {
		throw new GuardrailError(
			guardrailName,
			error?.description || error?.message || 'Unknown error',
			error?.description,
		);
	});
};

export async function runStageGuardrails({
	stageGuardrails,
	stage,
	inputText,
	failOnlyOnErrors,
}: RunStageGuardrailsOptions): Promise<GroupedGuardrailResults> {
	const guardrailPromises: Array<Promise<GuardrailResult>> = [];
	for (const guardrail of stageGuardrails[stage]) {
		guardrailPromises.push(
			wrapInGuardrailError(
				guardrail.name,

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Inspect the GuardrailError.guardrailName to identify which check threw, then debug that guardrail's check function.
  2. Make custom guardrail implementations throw errors with both `message` and `description` so the surfaced text is meaningful.
  3. Ensure guardrail check functions catch their own internal errors and return a structured GuardrailResult instead of throwing when the failure is a normal 'flagged' outcome.
  4. Reproduce the failing input in isolation against the named guardrail to find the triggering value.

Example fix

// before: guardrail throws a bare string
check: (text) => { if (bad(text)) throw 'invalid'; }
// after: throw an Error with description, or return a structured result
check: (text) => { if (bad(text)) throw new Error('invalid input'); }
Defensive patterns

Strategy: try-catch

Type guard

function isGuardrailError(e): e is GuardrailError { return e instanceof GuardrailError; }

Try / catch

try {
  await runStageGuardrails({ ... });
} catch (e) {
  if (e instanceof GuardrailError) {
    // e.guardrailName tells you which check failed
  }
}

Prevention

When it happens

Trigger: runStageGuardrails() wraps each guardrail.check(inputText) promise with wrapInGuardrailError. If the check function throws, rejects, or yields a non-GuardrailError, the wrapper converts it. Triggers: a guardrail check throwing a plain Error, a string, or undefined; an exception inside a custom guardrail implementation.

Common situations: A custom guardrail whose check function throws a non-standard error; a third-party guardrail raising an Error without a description; an unexpected runtime fault inside a guardrail (null dereference, bad cast).

Related errors


AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12). Data as JSON: /api/errors/ad2a8bca6b3ded79. Report an issue: GitHub.