n8n-io/n8n · error · Error
${toolName} policy.maxChildren must be a finite positive int
Error message
${toolName} policy.maxChildren must be a finite positive integer What it means
`resolveDelegateSubAgentPolicy` validates the `maxChildren` field of the delegation policy, which controls how many child sub-agent runs may execute in parallel. It defaults to `DEFAULT_SUB_AGENT_MAX_CHILDREN` (10) when undefined, then checks `Number.isFinite` and `Number.isInteger`. This throws when `maxChildren` is `NaN`, `Infinity`, `-Infinity`, a float (e.g. 2.5), or a non-number type that survived into the resolved policy.
Source
Thrown at packages/@n8n/agents/src/runtime/tools/delegate-sub-agent-tool.ts:375
toModelOutput?: (output: z.infer<typeof delegateSubAgentOutputSchema>) => unknown;
}
export type DelegateSubAgentToolMetadata = CreateDelegateSubAgentToolOptions;
function resolveDelegateSubAgentPolicy(
policy: DelegateSubAgentPolicy | undefined,
toolName: string,
): DelegateSubAgentPolicy {
const resolvedPolicy = {
...policy,
maxChildren: policy?.maxChildren ?? DEFAULT_SUB_AGENT_MAX_CHILDREN,
};
if (
!Number.isFinite(resolvedPolicy.maxChildren) ||
!Number.isInteger(resolvedPolicy.maxChildren)
) {
throw new Error(`${toolName} policy.maxChildren must be a finite positive integer`);
}
if (resolvedPolicy.maxChildren < 1) {
throw new Error(`${toolName} policy.maxChildren must be at least 1`);
}
return resolvedPolicy;
}
const DELEGATE_SUB_AGENT_TOOL_NAME_PATTERN = /^[a-zA-Z][a-zA-Z0-9_-]{0,63}$/;
function resolveDelegateSubAgentToolName(name: string | undefined): string {
if (name === undefined) return DELEGATE_SUB_AGENT_TOOL_NAME;
if (!DELEGATE_SUB_AGENT_TOOL_NAME_PATTERN.test(name)) {
throw new Error(
`Invalid delegate sub-agent tool name "${name}": must start with a letter and contain only letters, digits, underscores, and hyphens (max 64 characters)`,
);
}View on GitHub (pinned to 5ac6606e81)
Solutions
- Check the `maxChildren` value being passed — log it before the factory call.
- Coerce to an integer before passing: `Math.floor(Number(value))`, and validate it is finite.
- If the value comes from user input, validate with a Zod schema (`z.number().int().finite().positive()`) before it reaches the policy resolver.
- Omit `maxChildren` entirely if you want the default of 10.
Example fix
// before:
createDelegateSubAgentTool({ policy: { maxChildren: 2.5 } });
// after:
createDelegateSubAgentTool({ policy: { maxChildren: Math.floor(userInput) } });
// or omit for default:
createDelegateSubAgentTool({ }); // maxChildren defaults to 10 Defensive patterns
Strategy: validation
Validate before calling
function validateMaxChildren(value: unknown): number {
const n = Number(value);
if (!Number.isFinite(n) || !Number.isInteger(n)) {
throw new Error('maxChildren must be a finite integer');
}
return n;
}
const maxChildren = validateMaxChildren(policy?.maxChildren);
createDelegateSubAgentTool({ policy: { maxChildren } }); Type guard
function isFinitePositiveInteger(value: unknown): value is number {
return typeof value === 'number' && Number.isFinite(value) && Number.isInteger(value);
} Prevention
- Coerce maxChildren to an integer with Math.floor before passing.
- Validate with a Zod schema (z.number().int().finite().positive()) at the config boundary.
- Omit maxChildren entirely to use the default of 10.
When it happens
Trigger: Calling the delegate sub-agent tool factory with `policy: { maxChildren: NaN }`, `policy: { maxChildren: Infinity }`, `policy: { maxChildren: 2.5 }`, or `policy: { maxChildren: '5' as any }`. Also when `maxChildren` is parsed from user/config input that was not coerced to an integer.
Common situations: A UI or config field for 'max parallel sub-agents' accepted free-text and passed an uncoerced value. A JSON config had `maxChildren: 2.5` or `maxChildren: null` that was not caught upstream. Floating-point division produced a non-integer (e.g. `totalTasks / workers`).
Related errors
- ${toolName} policy.maxChildren must be at least 1
- Deferred tool name "${tool.name}" is reserved
- Duplicate deferred tool name "${tool.name}"
- Unable to convert tool to N8nTool: ${JSON.stringify(tool)}
- jitterRatio must be at least 0 and below 1, got ${lifecycleO
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/5492b41019040446.
Report an issue: GitHub.