Description
@ai-sdk/provider-utils@5.0.15 and later cannot be imported at all in any environment where globalThis.fetch is undefined. Because ai depends on it, ai becomes unimportable in those environments too.
safe-node-fetch evaluates this at module scope:
var initialGlobalFetch = globalThis.fetch;
var initialGlobalFetchIsNodeDefault = isNodeDefaultFetch(initialGlobalFetch);
function isNodeDefaultFetch(fetch) {
const source = Function.prototype.toString.call(fetch);
return source.includes("internal/deps/undici") || source.includes("lazy loading of undici");
}
Function.prototype.toString.call(undefined) throws:
TypeError: Function.prototype.toString requires that 'this' be a Function
Since the call runs at import time rather than lazily, there is no way for a consumer to avoid it — importing the package is enough to crash.
Expected: importing the package succeeds regardless of whether a global fetch exists; the safe-node-fetch optimization is skipped when it does not apply.
Actual: import throws TypeError.
Bisected: introduced in @ai-sdk/provider-utils@5.0.15. 5.0.14 and earlier are fine. Present through 5.0.23 (current latest). First reaches ai users via ai@7.0.42.
Real-world impact
Temporal's TypeScript SDK runs workflow code in a deterministic V8 sandbox that intentionally omits fetch (network I/O is not allowed in workflow code — it happens in activities). As of ai@7.0.42, importing ai inside a workflow throws at import time, so every workflow task fails:
TypeError: Function.prototype.toString requires that 'this' be a Function
at isNodeDefaultFetch (safe-node-fetch.ts:135:45)
at ./node_modules/@ai-sdk/provider-utils/dist/index.js (safe-node-fetch.ts:106:40)
at importWorkflows (workflows-autogenerated-entrypoint.cjs:13:9)
This should also affect other fetch-less contexts, such as Node running with --no-experimental-fetch and restricted VM/isolate embeddings.
Suggested fix
Guard the type before calling toString:
function isNodeDefaultFetch(fetch) {
if (typeof fetch !== 'function') return false;
const source = Function.prototype.toString.call(fetch);
return source.includes("internal/deps/undici") || source.includes("lazy loading of undici");
}
Ideally also defer the check so it is only evaluated when a download fetch is actually needed, rather than as a side effect of importing the module.
Reproduction
Minimal, no framework required:
npm i @ai-sdk/provider-utils@5.0.23
node -e "delete globalThis.fetch; require('@ai-sdk/provider-utils')"
# TypeError: Function.prototype.toString requires that 'this' be a Function
Passes on 5.0.14, throws on 5.0.15 and later. The control case (fetch present) imports fine.
AI SDK Version
@ai-sdk/provider-utils: 5.0.15 through 5.0.23 (5.0.14 unaffected)
ai: 7.0.42 and later (7.0.41 unaffected)
Code of Conduct
I agree to follow this project's Code of Conduct.
Description
@ai-sdk/provider-utils@5.0.15and later cannot be imported at all in any environment whereglobalThis.fetchis undefined. Becauseaidepends on it,aibecomes unimportable in those environments too.safe-node-fetchevaluates this at module scope:Function.prototype.toString.call(undefined)throws:Since the call runs at import time rather than lazily, there is no way for a consumer to avoid it — importing the package is enough to crash.
Expected: importing the package succeeds regardless of whether a global
fetchexists; the safe-node-fetch optimization is skipped when it does not apply.Actual: import throws
TypeError.Bisected: introduced in
@ai-sdk/provider-utils@5.0.15. 5.0.14 and earlier are fine. Present through 5.0.23 (current latest). First reachesaiusers viaai@7.0.42.Real-world impact
Temporal's TypeScript SDK runs workflow code in a deterministic V8 sandbox that intentionally omits
fetch(network I/O is not allowed in workflow code — it happens in activities). As ofai@7.0.42, importingaiinside a workflow throws at import time, so every workflow task fails:This should also affect other fetch-less contexts, such as Node running with
--no-experimental-fetchand restricted VM/isolate embeddings.Suggested fix
Guard the type before calling
toString:Ideally also defer the check so it is only evaluated when a download fetch is actually needed, rather than as a side effect of importing the module.
Reproduction
Minimal, no framework required:
Passes on
5.0.14, throws on5.0.15and later. The control case (fetchpresent) imports fine.AI SDK Version
@ai-sdk/provider-utils: 5.0.15 through 5.0.23 (5.0.14 unaffected)ai: 7.0.42 and later (7.0.41 unaffected)Code of Conduct
I agree to follow this project's Code of Conduct.