mastra-ai/mastra · error
@mastra/livekit: `configuration.endCall` has no effect with
Error message
@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.
What it means
`configuration.endCall` lets the built-in agent/workflow paths detect an end-call tool invocation and hang up. With a custom `generate` function, the worker never sees the model's tool calls, so endCall would silently do nothing; instead of failing at runtime, the library throws at construction time.
Source
Thrown at integrations/livekit/src/worker.ts:799
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).
if (options.turnDetection === 'multilingual' || options.turnDetection === 'english') {
requestEouMethod(EOU_METHODS[options.turnDetection]);
queueWorkerSetup(
import('@livekit/agents-plugin-livekit')
.then(() => {
// The plugin registers both language runners; keep only the requested ones soView on GitHub (pinned to 75dd419e61)
Solutions
- Remove `configuration.endCall` when using `generate`.
- Detect the end-call tool inside your `generate` function and invoke `runEndCall` directly from there.
Example fix
// before
createLiveKitWorker({ generate: myGenerate, configuration: { endCall: myEndCallConfig } });
// after
createLiveKitWorker({
generate: async (ctx) => {
const reply = await produceReply(ctx);
if (reply.callsEndCallTool) await ctx.runEndCall();
return reply;
},
}); Defensive patterns
Strategy: validation
Validate before calling
if (options.generate && options.configuration?.endCall) throw new Error('configuration.endCall is unsupported with generate; call runEndCall from your generator instead'); Type guard
function endCallConfigCompatible(o: { generate?: unknown; configuration?: { endCall?: unknown } }): boolean {
return !(o.generate != null && o.configuration?.endCall != null);
} Try / catch
try {
const worker = createLiveKitWorker(options);
} catch (e) {
if ((e as Error).message.includes('endCall has no effect with generate')) {
console.error('Remove configuration.endCall and call runEndCall inside your generator');
} else throw e;
} Prevention
- Only configure configuration.endCall for agent/workflow workers
- Encapsulate end-call detection in your generate function via runEndCall
- Centralize worker option building in one typed factory to keep incompatible combos unrepresentable
When it happens
Trigger: createLiveKitWorker({ generate: myGenerator, configuration: { endCall: {...} } }) — the guard `options.generate && options.configuration?.endCall` fires.
Common situations: Enabling endCall on a custom generator config copied from an agent-based example; adding a `generate` callback later without removing the endCall configuration set earlier.
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: `workflowInput` is required when `workflow`
- Google RBAC roleMapping is required.
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/cffb7a36b58b0353.
Report an issue: GitHub.