{"record":{"id":"f609fa75e70004e5","repo":"continuedev/continue","slug":"either-streamcompletion-or-streamchat-must-be-defi","errorCode":null,"errorMessage":"Either streamCompletion or streamChat must be defined in a custom LLM in config.ts","messagePattern":"Either streamCompletion or streamChat must be defined in a custom LLM in config\\.ts","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"core/llm/llms/CustomLLM.ts","lineNumber":83,"sourceCode":"        (...args) => this.fetch(...args),\n      )) {\n        yield content;\n      }\n    } else if (this.customStreamChat) {\n      for await (const content of this.customStreamChat(\n        [{ role: \"user\", content: prompt }],\n        signal,\n        options,\n        (...args) => this.fetch(...args),\n      )) {\n        if (typeof content === \"string\") {\n          yield content;\n        } else {\n          yield renderChatMessage(content);\n        }\n      }\n    } else {\n      throw new Error(\n        \"Either streamCompletion or streamChat must be defined in a custom LLM in config.ts\",\n      );\n    }\n  }\n}\n\nexport default CustomLLMClass;\n","sourceCodeStart":65,"sourceCodeEnd":91,"githubUrl":"https://github.com/continuedev/continue/blob/5522c6f44ca0ac3528b37244818fbfa39b5af470/core/llm/llms/CustomLLM.ts#L65-L91","documentation":"Thrown by CustomLLM._streamComplete when the user-supplied custom LLM object in config.ts defines neither streamCompletion nor streamChat. The custom provider has no way to generate text, so the first completion attempt fails immediately with this config error.","triggerScenarios":"Defining a custom LLM entry in config.ts with only non-streaming methods (e.g. just complete), misspelling streamCompletion/streamChat (e.g. streamCompletions), or passing an empty object/class instance as the custom provider.","commonSituations":"Users porting a non-streaming custom provider from another framework, method renamed during refactor, or providing the functions as arrow properties under the wrong key so the presence check fails.","solutions":["Implement at least one of async function* streamCompletion(prompt) or async function* streamChat(messages) on the custom object","Check spelling and that they are generator functions (use function* syntax or yield)","Return/throw cleanly from config.ts if the custom provider isn't configured, instead of an empty object","Add a startup smoke test that calls streamComplete once"],"exampleFix":"// before\nconfig.llm = { provider: 'custom', options: { streamCompletion2: async function* () {} } };\n// after\nconfig.llm = { provider: 'custom', options: { streamCompletion: async function* (prompt) { yield 'ok'; } } };","handlingStrategy":"validation","validationCode":"const custom = config.llm.options;\nif (typeof custom.streamCompletion !== 'function' && typeof custom.streamChat !== 'function') {\n  throw new Error('Custom LLM must implement streamCompletion or streamChat');\n}","typeGuard":"function isValidCustomLLM(o: unknown): o is { streamChat?: Function; streamCompletion?: Function } {\n  return !!o && (typeof (o as any).streamChat === 'function' || typeof (o as any).streamCompletion === 'function');\n}","tryCatchPattern":"try { yield* llm.streamComplete(p); }\ncatch (e) {\n  if (e instanceof Error && e.message.includes('custom LLM')) throw new ConfigError(e.message);\n  throw e;\n}","preventionTips":["Assert the required method exists in a config test","Name stream methods exactly streamCompletion/streamChat","Add a smoke-test completion in CI"],"tags":["custom-llm","config","typescript","provider"],"backgroundTag":"missing-required-method","analyzedSha":"5522c6f44ca0ac3528b37244818fbfa39b5af470","analyzedAt":"2026-08-27T11:28:54.683Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}