continuedev/continue · error · Error

Either streamCompletion or streamChat must be defined in a c

Error message

Either streamCompletion or streamChat must be defined in a custom LLM in config.ts

What it means

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.

Source

Thrown at core/llm/llms/CustomLLM.ts:83

        (...args) => this.fetch(...args),
      )) {
        yield content;
      }
    } else if (this.customStreamChat) {
      for await (const content of this.customStreamChat(
        [{ role: "user", content: prompt }],
        signal,
        options,
        (...args) => this.fetch(...args),
      )) {
        if (typeof content === "string") {
          yield content;
        } else {
          yield renderChatMessage(content);
        }
      }
    } else {
      throw new Error(
        "Either streamCompletion or streamChat must be defined in a custom LLM in config.ts",
      );
    }
  }
}

export default CustomLLMClass;

View on GitHub (pinned to 5522c6f44c)

Solutions

  1. Implement at least one of async function* streamCompletion(prompt) or async function* streamChat(messages) on the custom object
  2. Check spelling and that they are generator functions (use function* syntax or yield)
  3. Return/throw cleanly from config.ts if the custom provider isn't configured, instead of an empty object
  4. Add a startup smoke test that calls streamComplete once

Example fix

// before
config.llm = { provider: 'custom', options: { streamCompletion2: async function* () {} } };
// after
config.llm = { provider: 'custom', options: { streamCompletion: async function* (prompt) { yield 'ok'; } } };
Defensive patterns

Strategy: validation

Validate before calling

const custom = config.llm.options;
if (typeof custom.streamCompletion !== 'function' && typeof custom.streamChat !== 'function') {
  throw new Error('Custom LLM must implement streamCompletion or streamChat');
}

Type guard

function isValidCustomLLM(o: unknown): o is { streamChat?: Function; streamCompletion?: Function } {
  return !!o && (typeof (o as any).streamChat === 'function' || typeof (o as any).streamCompletion === 'function');
}

Try / catch

try { yield* llm.streamComplete(p); }
catch (e) {
  if (e instanceof Error && e.message.includes('custom LLM')) throw new ConfigError(e.message);
  throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of continuedev/continue@5522c6f44c (2026-08-27). Data as JSON: /api/errors/f609fa75e70004e5. Report an issue: GitHub.