eyaltoledano/claude-task-master · error
Provider must implement BaseAIProvider interface
Error message
Provider must implement BaseAIProvider interface
What it means
registerProvider() enforces the BaseAIProvider contract: any registered provider must implement generateText, streamText, and generateObject as functions. This duck-typing check runs at registration time so that lookup failures surface early instead of when a consumer first calls the provider. Passing a plain object, a partial implementation, or a misnamed method triggers this error.
Source
Thrown at src/provider-registry/index.js:70
* @param {object} options - Additional options for registration
* @returns {ProviderRegistry} The singleton instance for chaining
*/
registerProvider(providerName, provider, options = {}) {
if (!providerName || typeof providerName !== 'string') {
throw new Error('Provider name must be a non-empty string');
}
if (!provider) {
throw new Error('Provider instance is required');
}
// Validate that provider implements the required interface
if (
typeof provider.generateText !== 'function' ||
typeof provider.streamText !== 'function' ||
typeof provider.generateObject !== 'function'
) {
throw new Error('Provider must implement BaseAIProvider interface');
}
// Add provider to the registry
this._providers.set(providerName, {
instance: provider,
options,
registeredAt: new Date()
});
return this;
}
/**
* Check if a provider exists in the registry
* @param {string} providerName - The name of the provider
* @returns {boolean} True if the provider exists
*/
hasProvider(providerName) {View on GitHub (pinned to c0c98d367c)
Solutions
- Extend BaseAIProvider (or implement all three methods: generateText, streamText, generateObject) before registering.
- console.log(typeof p.generateText, typeof p.streamText, typeof p.generateObject) to see which method is missing.
- If you meant to pass a class, instantiate it: new MyProvider() so prototype methods exist on the instance.
- Update your stub/mock to implement the full interface when testing.
- Check for version drift between your provider package and the registry's expected interface.
Example fix
// before
registry.registerProvider('custom', {
generateText: async (p) => 'hi'
});
// after
class CustomProvider extends BaseAIProvider {
async generateText(prompt) { return 'hi'; }
async streamText(prompt, cb) { cb('hi'); }
async generateObject(prompt, schema) { return {}; }
}
registry.registerProvider('custom', new CustomProvider()); Defensive patterns
Strategy: validation
Validate before calling
function assertImplementsBaseAIProvider(p) {
const required = ['generateText', 'streamText', 'generateObject'];
const missing = required.filter((m) => typeof p?.[m] !== 'function');
if (missing.length) {
throw new TypeError(`Provider missing BaseAIProvider methods: ${missing.join(', ')}`);
}
}
assertImplementsBaseAIProvider(myProvider);
registry.registerProvider('custom', myProvider); Type guard
const implementsBaseAIProvider = (p) => p != null && typeof p.generateText === 'function' && typeof p.streamText === 'function' && typeof p.generateObject === 'function';
Try / catch
try {
registry.registerProvider('custom', provider);
} catch (err) {
if (err.message.includes('BaseAIProvider interface')) {
console.error('Provider', provider?.constructor?.name, 'must implement generateText, streamText, generateObject');
provider = new BaseAIProviderAdapter(provider); // wrap/adapt
registry.registerProvider('custom', provider);
return;
}
throw err;
} Prevention
- Always extend BaseAIProvider for custom providers.
- Implement all three interface methods even if some are stubs that throw 'not supported'.
- Instantiate classes (new X()) rather than registering the class itself.
- Pin provider-package versions and review changelogs for interface method renames.
- Write a shared test asserting your provider passes the interface check.
When it happens
Trigger: registerProvider('custom', { generateText: fn }) missing streamText/generateObject; registering a class reference instead of an instance (methods not bound/instance methods not on the object); a v2 provider with renamed methods registered into a registry expecting the BaseAIProvider interface.
Common situations: Writing a custom provider from docs and only implementing one or two methods; refactoring method names (e.g. generate → generateText) without updating all interface methods; mocking providers in tests with incomplete stubs; registering objects that proxy methods via getters, which typeof checks at registration may miss if lazily defined.
Related errors
- Provider name must be a non-empty string
- Provider instance is required
- MFA_VERIFICATION_FAILED
- Failed to initialize services: ${(error as Error).message}
- Invalid format: ${options.format}. Valid formats are: text,
AI-assisted analysis of eyaltoledano/claude-task-master@c0c98d367c (2026-08-29).
Data as JSON: /api/errors/c1286c86c1b1002e.
Report an issue: GitHub.