{"record":{"id":"418cc02309e64b3f","repo":"earendil-works/pi","slug":"no-default-stream-function-configured-pass-stream","errorCode":null,"errorMessage":"No default stream function configured. Pass streamFn explicitly or call setDefaultStreamFn().","messagePattern":"No default stream function configured\\. Pass streamFn explicitly or call setDefaultStreamFn\\(\\)\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/agent/src/stream-fn.ts","lineNumber":17,"sourceCode":"import type { StreamFn } from \"./types.ts\";\n\nlet defaultStreamFn: StreamFn | undefined;\n\n/**\n * Configure the fallback used by Agent and low-level loops when callers omit streamFn.\n *\n * Hosts that provide a default model runtime can install its stream function here\n * without making pi-agent-core depend on a provider catalog or compatibility layer.\n */\nexport function setDefaultStreamFn(streamFn: StreamFn | undefined): void {\n\tdefaultStreamFn = streamFn;\n}\n\nexport function getDefaultStreamFn(): StreamFn {\n\tif (!defaultStreamFn) {\n\t\tthrow new Error(\"No default stream function configured. Pass streamFn explicitly or call setDefaultStreamFn().\");\n\t}\n\treturn defaultStreamFn;\n}\n","sourceCodeStart":1,"sourceCodeEnd":21,"githubUrl":"https://github.com/earendil-works/pi/blob/4af9d21d3b4d664e4a29fcabfec85171077248e3/packages/agent/src/stream-fn.ts#L1-L21","documentation":"pi-agent-core ships no built-in provider runtime: Agent and the runAgentLoop/runAgentLoopContinue functions fall back to getDefaultStreamFn() when the caller omits streamFn, and that getter throws until the host registers an implementation with setDefaultStreamFn() (stream-fn.ts:17). The error means the process was wired without ever deciding how model calls reach a provider - it fails fast at construction/loop start, before any request is attempted.","triggerScenarios":"Constructing new Agent({ model }) or calling runAgentLoop without streamFn before any setDefaultStreamFn call; registering the default in a different copy of the module (duplicate package installs or mixed ESM/CJS resolution) so the Agent reads an unset instance; calling setDefaultStreamFn(undefined) during teardown and then creating a new Agent.","commonSituations":"New host apps embedding the agent core without wiring a runtime; upgrades that moved or renamed the setup call; monorepos loading two versions of the package; import-order or tree-shaking changes dropping the setup module's side effect.","solutions":["Pass streamFn explicitly when constructing the Agent or calling runAgentLoop - immune to module-instance issues","Otherwise call setDefaultStreamFn(stream) once at app startup, before any Agent is created","If you already called it, check for duplicate copies of the agent package (npm ls, lockfile audit) and dedupe","Make sure the module that performs setup is imported for its side effects early in the entrypoint"],"exampleFix":"// before\nconst agent = new Agent({ model }); // throws: no default stream function\n\n// after - pass it explicitly (or register once at startup)\nimport { stream } from \"@earendil-works/pi-ai\";\nconst agent = new Agent({ model, streamFn: stream });\n// or, at app startup:\nsetDefaultStreamFn(stream);","handlingStrategy":"validation","validationCode":"import { getDefaultStreamFn } from \"@earendil-works/pi-agent-core\";\n\nfunction hasStreamRuntime(): boolean {\n  try {\n    getDefaultStreamFn();\n    return true;\n  } catch {\n    return false;\n  }\n}\n\nif (!hasStreamRuntime() && !options.streamFn) {\n  throw new Error(\"Configure a stream function before creating Agents\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  const agent = new Agent({ model });\n} catch (e) {\n  if (e instanceof Error && e.message.includes(\"No default stream function\")) {\n    failFastWithConfigGuidance(); // wire streamFn or setDefaultStreamFn, then restart\n  }\n  throw e;\n}","preventionTips":["Prefer passing streamFn explicitly at every Agent construction site","Otherwise centralize setDefaultStreamFn(stream) in the app entrypoint before any Agent exists","After dependency upgrades, run a smoke test that constructs an Agent to catch wiring regressions","Deduplicate package versions in monorepos so the registered default and the reader share one module instance"],"tags":["configuration","initialization","agent-loop","stream-fn","dependency-injection"],"backgroundTag":"missing-default-configuration","analyzedSha":"4af9d21d3b4d664e4a29fcabfec85171077248e3","analyzedAt":"2026-08-24T13:07:14.692Z","schemaVersion":2},"datasetVersion":"2026-08-24T17:17:21.512Z"}