affaan-m/ECC · error · NotImplementedError

{self.__class__.__name__} must implement get_default_model

Error message

{self.__class__.__name__} must implement get_default_model

What it means

LLMProvider is an ABC with three abstractmethods (generate, list_models, validate_config) but get_default_model is a concrete method whose default body raises NotImplementedError. A subclass that fails to override get_default_model will instantiate fine (it is not abstract) but blow up at the first call.

Source

Thrown at src/llm/core/interface.py:30

    provider_type: ProviderType

    @abstractmethod
    def generate(self, input: LLMInput) -> LLMOutput: ...

    @abstractmethod
    def list_models(self) -> list[ModelInfo]: ...

    @abstractmethod
    def validate_config(self) -> bool: ...

    def supports_tools(self) -> bool:
        return True

    def supports_vision(self) -> bool:
        return False

    def get_default_model(self) -> str:
        raise NotImplementedError(f"{self.__class__.__name__} must implement get_default_model")


class LLMError(Exception):
    def __init__(
        self,
        message: str,
        provider: ProviderType | None = None,
        code: str | None = None,
        details: dict[str, Any] | None = None,
    ) -> None:
        super().__init__(message)
        self.message = message
        self.provider = provider
        self.code = code
        self.details = details or {}


class AuthenticationError(LLMError): ...

View on GitHub (pinned to 01e15490f0)

Solutions

  1. Override get_default_model in the subclass to return self.default_model (or whatever the provider's default is).
  2. Alternatively, make get_default_model an @abstractmethod so the error surfaces at construction, not at call time.
  3. Add a unit test that calls get_default_model() on every provider in the registry.

Example fix

# before
class MyProvider(LLMProvider):
    provider_type = ProviderType.MINE
    def generate(self, llm_input): ...
    def list_models(self): return []
    def validate_config(self): return True

# after
class MyProvider(LLMProvider):
    provider_type = ProviderType.MINE
    default_model = 'mine-1'
    def generate(self, llm_input): ...
    def list_models(self): return []
    def validate_config(self): return True
    def get_default_model(self) -> str:
        return self.default_model
Defensive patterns

Strategy: type-guard

Validate before calling

from llm.core.interface import LLMProvider

def assert_provider_complete(p: LLMProvider) -> None:
    p.get_default_model()  # fail fast at construction/wire-up time

Type guard

from llm.core.interface import LLMProvider

def has_default_model(p: LLMProvider) -> bool:
    try:
        p.get_default_model()
        return True
    except NotImplementedError:
        return False

Try / catch

try:
    model = provider.get_default_model()
except NotImplementedError:
    model = 'fallback-model-id'

Prevention

When it happens

Trigger: Subclassing LLMProvider (e.g. a new provider adapter) and forgetting to define get_default_model; calling provider.get_default_model() on a partially implemented provider; an old subclass predating the addition of get_default_model.

Common situations: Adding a new provider to the llm package without copying the get_default_model override pattern used by AstraflowProvider/AtlasProvider; a test fixture that subclasses the base without overriding every method.

Related errors


AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13). Data as JSON: /api/errors/908da0cd612dc079. Report an issue: GitHub.