mastra-ai/mastra · error
@mastra/livekit: `workflowInput` is required when `workflow`
Error message
@mastra/livekit: `workflowInput` is required when `workflow` is set. Map the turn into the workflow inputData, e.g. workflowInput: ({ chatCtx }) => ({ history: chatContextToMessages(chatCtx) }). What it means
When `workflow` is the reply generator, the worker needs a `workflowInput` mapper to turn the LiveKit chat context into the workflow's inputData schema; without it the workflow would receive no input and fail. The library therefore requires `workflowInput` whenever `workflow` is set.
Source
Thrown at integrations/livekit/src/worker.ts:793
*
* if (process.argv[1] === fileURLToPath(import.meta.url)) {
* runLiveKitWorker({ entry: import.meta.url, agentName: 'mastra-voice' });
* }
* ```
*/
export function createLiveKitWorker(options: CreateLiveKitWorkerOptions) {
if (options.generate && (options.agent || options.workflow)) {
throw new Error(
'@mastra/livekit: set exactly one reply generator — `generate`, `agent`, or `workflow` — not a combination.',
);
}
if (options.agent && options.workflow) {
throw new Error(
'@mastra/livekit: set `agent` or `workflow`, not both — they are mutually exclusive reply generators.',
);
}
if (options.workflow && !options.workflowInput) {
throw new Error(
'@mastra/livekit: `workflowInput` is required when `workflow` is set. Map the turn into the ' +
'workflow inputData, e.g. workflowInput: ({ chatCtx }) => ({ history: chatContextToMessages(chatCtx) }).',
);
}
if (options.generate && options.configuration?.endCall) {
throw new Error(
'@mastra/livekit: `configuration.endCall` has no effect with `generate` — the worker cannot observe ' +
'tool calls from a custom reply generator. Detect the end-call tool inside your generator and call ' +
'`runEndCall` directly instead.',
);
}
const wantsSileroVad = options.vad === undefined || options.vad === 'silero';
// The turn detector's inference runners register at plugin-import time, and the agent
// server only spawns its inference process for runners registered before it starts —
// so begin the import now (worker definition happens at module scope, before
// runLiveKitWorker boots the server, which awaits this).View on GitHub (pinned to 75dd419e61)
Solutions
- Add a workflowInput function that maps ({ chatCtx }) to the workflow inputData, e.g. ({ chatCtx }) => ({ history: chatContextToMessages(chatCtx) }).
- Match the returned object to the workflow's zod input schema field names exactly.
Example fix
// before
createLiveKitWorker({ workflow: myWorkflow });
// after
createLiveKitWorker({
workflow: myWorkflow,
workflowInput: ({ chatCtx }) => ({ history: chatContextToMessages(chatCtx) }),
}); Defensive patterns
Strategy: validation
Validate before calling
if (options.workflow && !options.workflowInput) throw new Error('workflowInput is required when workflow is set'); Type guard
function workflowOptionsValid(o: { workflow?: unknown; workflowInput?: unknown }): boolean {
return o.workflow == null || typeof o.workflowInput === 'function';
} Try / catch
try {
const worker = createLiveKitWorker(options);
} catch (e) {
if ((e as Error).message.includes('workflowInput is required')) {
console.error('Add workflowInput: ({ chatCtx }) => ({ ... }) matching your workflow input schema');
} else throw e;
} Prevention
- Always pair workflow with a workflowInput mapper derived from the workflow's zod input schema
- Validate the workflowInput return shape against the input schema in a unit test
- Reuse a shared helper like chatContextToMessages instead of ad-hoc mappers
When it happens
Trigger: createLiveKitWorker({ workflow: myWorkflow }) with options.workflowInput undefined — the guard `options.workflow && !options.workflowInput` fires.
Common situations: Building a workflow-based voice agent and missing the required companion option; converting a sample that used `agent` (no input mapper needed) to `workflow`; TypeScript types bypassed via `as` casts or loose typing.
Related errors
- @mastra/livekit: MastraLLM requires exactly one reply source
- @mastra/livekit: set exactly one reply generator — `generate
- @mastra/livekit: set `agent` or `workflow`, not both — they
- @mastra/livekit: `configuration.endCall` has no effect with
- Workflow "${params.id}" declares an array of schedules but o
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/606e8d329c6e378f.
Report an issue: GitHub.