mastra-ai/mastra · error
@mastra/livekit: no fetch implementation available; pass `fe
Error message
@mastra/livekit: no fetch implementation available; pass `fetch` or run on Node ≥ 22.
What it means
createRemoteAgentReplyGenerator posts to the Mastra agent stream endpoint over HTTP and needs a fetch implementation. If no explicit `fetch` option was supplied and the runtime does not expose a global fetch (Node < 22 without a polyfill, or a runtime without fetch), it throws instead of failing later at request time.
Source
Thrown at integrations/livekit/src/remote.ts:182
* indefinite dead air.
*/
export function createRemoteAgentReplyGenerator(options: RemoteAgentReplyGeneratorOptions): VoiceReplyGenerator {
const {
baseUrl,
agentId,
apiPrefix = DEFAULT_API_PREFIX,
headers,
fetch: fetchImpl = globalThis.fetch,
timeoutMs = DEFAULT_REMOTE_TIMEOUT_MS,
retries = DEFAULT_REMOTE_RETRIES,
body: extraBody,
toolFeedback,
onToolCall,
onTurnComplete,
} = options;
if (!fetchImpl) {
throw new Error('@mastra/livekit: no fetch implementation available; pass `fetch` or run on Node ≥ 22.');
}
const url = `${trimTrailingSlash(baseUrl)}${apiPrefix}/agents/${agentId}/stream`;
return ctx => {
if (ctx.messages.length === 0) return null;
// Reassigned per retry attempt (see the loop below) so a watchdog abort on one attempt can't
// poison the next; `cancel()` always aborts whichever attempt is currently in flight.
let currentAbortController: AbortController | undefined;
let cancelled = false;
// Accumulated as the turn streams so the post-turn hook sees what was actually produced.
let replyText = '';
const toolCalls: VoiceToolCall[] = [];
let usage: VoiceTurnUsage | undefined;
const emitTurnComplete = (interrupted: boolean) => {
if (!onTurnComplete) return;
const completeCtx: VoiceTurnCompleteContext = {View on GitHub (pinned to 75dd419e61)
Solutions
- Run on Node 22 or newer, where global fetch satisfies the requirement.
- Pass an explicit fetch implementation via the `fetch` option (e.g. undici's fetch or node-fetch).
- Install a fetch polyfill that sets globalThis.fetch before creating the reply generator.
Example fix
// before
createRemoteAgentReplyGenerator({ baseUrl, agentId }); // Node 20
// after
import { fetch } from 'undici';
createRemoteAgentReplyGenerator({ baseUrl, agentId, fetch }); Defensive patterns
Strategy: validation
Validate before calling
if (typeof fetch !== 'function') {
throw new Error('This runtime has no global fetch; upgrade to Node >= 22 or pass a `fetch` option.');
}
// then safely:
createRemoteAgentReplyGenerator({ baseUrl, agentId }); Type guard
function hasFetch(r): r is typeof globalThis & { fetch: typeof fetch } {
return typeof (r as { fetch?: unknown }).fetch === 'function';
} Try / catch
try {
const gen = createRemoteAgentReplyGenerator(opts);
} catch (e) {
if (e instanceof Error && e.message.includes('no fetch implementation')) {
const gen = createRemoteAgentReplyGenerator({ ...opts, fetch: (await import('undici')).fetch });
} else throw e;
} Prevention
- Pin engines.node >= 22 in package.json for voice worker services.
- Centralize fetch resolution (undici/node-fetch fallback) in one config module.
- Add a startup smoke check that global fetch exists before spawning workers.
When it happens
Trigger: Calling createRemoteAgentReplyGenerator (directly or via the MastraLLM `remote` option) on Node < 22 or an environment without global fetch, without passing a `fetch` implementation in options.
Common situations: Running voice workers on Node 18/20 where global fetch is experimental or absent per the library's requirement; bundling for edge runtimes that lack fetch under the expected global; polyfills not installed.
Related errors
- @mastra/livekit: Mastra agent stream request failed with sta
- @mastra/livekit: Mastra agent stream returned an empty respo
- Token exchange failed: ${error}
- Failed to fetch user info from Auth0
- Token exchange failed: ${error}
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/04568621c56837fa.
Report an issue: GitHub.