mastra-ai/mastra · error · FactoryRuleValidationError
Factory skill cancelInFlight must be a boolean.
Error message
Factory skill cancelInFlight must be a boolean.
What it means
The optional cancelInFlight field on an invoke-skill decision controls whether an in-flight run of the same key is cancelled; it must be a real boolean when provided. Passing a truthy/falsy non-boolean (strings 'true'/'false', 0/1, null) is rejected so downstream logic can rely on strict boolean semantics.
Source
Thrown at mastracode/factory/src/rules/validation.ts:297
assertExactKeys(
value,
['type', 'idempotencyKey', 'role', 'skillName', 'prompt', 'arguments', 'precedingMessage', 'cancelInFlight'],
'Factory invoke skill decision',
);
// A run activates a skill or carries a prompt, never both: they are two
// ways to author the same kickoff message, so accepting both would leave
// the dispatcher picking a winner.
if ((value.skillName === undefined) === (value.prompt === undefined)) {
throw new FactoryRuleValidationError('Factory skill invocation needs exactly one of skillName or prompt.');
}
const args = optionalBoundedString(value.arguments, 'Factory skill arguments', MAX_ARGUMENTS_LENGTH);
const precedingMessage = optionalBoundedString(
value.precedingMessage,
'Factory skill preceding message',
MAX_MESSAGE_LENGTH,
);
if (value.cancelInFlight !== undefined && typeof value.cancelInFlight !== 'boolean') {
throw new FactoryRuleValidationError('Factory skill cancelInFlight must be a boolean.');
}
return {
type,
...commonCommitFields(value),
role: boundedString(value.role, 'Factory skill role', MAX_ROLE_LENGTH, IDENTIFIER_RE),
...(value.skillName === undefined
? { prompt: boundedString(value.prompt, 'Factory skill prompt', MAX_MESSAGE_LENGTH) }
: { skillName: boundedString(value.skillName, 'Factory skill name', MAX_SKILL_NAME_LENGTH, SKILL_NAME_RE) }),
...(args ? { arguments: args } : {}),
...(precedingMessage ? { precedingMessage } : {}),
...(value.cancelInFlight === true ? { cancelInFlight: true } : {}),
};
}
case 'sendMessage': {
assertExactKeys(
value,
['type', 'idempotencyKey', 'role', 'message', 'priority', 'idleBehavior', 'prepareBinding'],
'Factory send message decision',View on GitHub (pinned to 75dd419e61)
Solutions
- Coerce config values to real booleans with === 'true' or Boolean(...) before assigning, but avoid passing null (use undefined to omit).
- Use undefined (field absent) rather than null when no cancel behavior is intended.
- Normalize YAML parsing with a schema (e.g. zod boolean) at config-load time.
Example fix
// before cancelInFlight: config.cancelInFlight // 'true' (string from env/YAML) // after cancelInFlight: config.cancelInFlight === undefined ? undefined : config.cancelInFlight === true || config.cancelInFlight === 'true'
Defensive patterns
Strategy: type-guard
Validate before calling
function checkCancelInFlight(d) {
if (d.cancelInFlight !== undefined && typeof d.cancelInFlight !== 'boolean') {
throw new Error('cancelInFlight must be boolean or omitted');
}
} Type guard
function hasValidCancelFlag(d: { cancelInFlight?: unknown }): d is { cancelInFlight?: boolean } {
const { cancelInFlight } = d;
return cancelInFlight === undefined || typeof cancelInFlight === 'boolean';
} Try / catch
try {
commitDecision(decision);
} catch (e) {
if (e instanceof FactoryRuleValidationError && /cancelInFlight must be a boolean/.test(e.message)) {
const { cancelInFlight, ...rest } = decision;
return commitDecision({ ...rest, cancelInFlight: cancelInFlight === true });
}
throw e;
} Prevention
- Parse YAML/env config with a schema enforcing boolean before use.
- Never assign null or 0/1 to boolean flags; use undefined to omit.
- Coerce string booleans at the config boundary, not at decision-build time.
When it happens
Trigger: Emitting an invoke-skill decision where value.cancelInFlight is defined but not typeof 'boolean' — e.g. cancelInFlight: 'true' from parsed JSON/YAML config, cancelInFlight: 1, or cancelInFlight: null.
Common situations: Rules whose options come from YAML/JSON config or environment variables where booleans deserialize as strings; template interpolation producing numbers; API responses carrying 0/1 flags.
Related errors
- ${label} must be an object.
- ${label}.${stage} must be an object.
- ${label}.${stage}.${source} handlers must be functions.
- Factory message prepareBinding must be a boolean.
- Factory rule version is required.
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/1a785701de299ff3.
Report an issue: GitHub.