Class OllamaProviderErrorMapper

java.lang.Object
com.tnsai.llm.errors.OllamaProviderErrorMapper
All Implemented Interfaces:
ProviderErrorMapper

public class OllamaProviderErrorMapper extends Object implements ProviderErrorMapper
ProviderErrorMapper for Ollama, the local-first LLM runtime that runs models on the host machine (http://localhost:11434 by default).

Ollama's error envelope is intentionally minimal — a single free-text string under error, with no structured code or type field:


 { "error": "model 'foo' not found, try pulling it first" }
 

Without a structured code, classification is heuristic: sniff the message text for known phrases. The phrases below are stable across recent Ollama versions (verified against the canonical server.go error sites).

Status mappings:

  • Message contains "not found" or "no such model" → MODEL_NOT_FOUND (the most common Ollama failure: user referenced a model they haven't pulled yet)
  • Message contains "context" or "exceeds" (case-insensitive) → CONTEXT_TOO_LONG
  • Message contains "out of memory" or "VRAM" → MODEL_OVERLOADED (Ollama can't load the model — usually the host is out of GPU memory)
  • HTTP 503 → MODEL_OVERLOADED (daemon temporarily unavailable)
  • HTTP 5xx → SERVER_ERROR
  • HTTP 401/403 → AUTHENTICATION_FAILED (Ollama itself doesn't authenticate, but reverse proxies in front of it might)
  • HTTP 4xx → INVALID_REQUEST (fallback)

No headers are captured — Ollama's local responses don't carry meaningful diagnostic headers, and the retry-after idiom doesn't apply to a single-host runtime that's either running or not. The empty relevantHeaders map keeps log payloads lean.

Note on connection failures: when Ollama isn't running at all, the request fails at the TCP layer with ConnectException — that doesn't reach this mapper (executeRequest only invokes mappers for non-2xx HTTP responses). Connection errors land in the legacy IOException catch path, which is the right place for "the daemon isn't running, start it" advice.

Since:
0.5.1 (issue #87 follow-up — fourth pilot mapper)
  • Constructor Details

    • OllamaProviderErrorMapper

      public OllamaProviderErrorMapper()
  • Method Details

    • providerId

      public String providerId()
      Specified by:
      providerId in interface ProviderErrorMapper
      Returns:
      short, lowercase provider id (e.g. "openai", "anthropic"). Used to route a raw response to the right mapper.
    • map

      public com.tnsai.exceptions.LLMException map(int httpStatus, Map<String,String> responseHeaders, String responseBody, String model, Throwable cause)
      Description copied from interface: ProviderErrorMapper
      Translate a raw HTTP error response into a typed LLMException.
      Specified by:
      map in interface ProviderErrorMapper
      Parameters:
      httpStatus - HTTP status code from the response
      responseHeaders - selected response headers (lower-cased keys); empty map if none captured
      responseBody - raw response body; mapper parses provider-specific envelope (e.g. JSON error.code)
      model - model identifier from the request, for the resulting LLMException.getModel()
      cause - underlying transport throwable, may be null when the failure is purely a non-2xx response
      Returns:
      typed LLMException with ProviderDetails attached
    • mapErrorType

      public Optional<com.tnsai.exceptions.LLMException.ErrorType> mapErrorType(String providerCode)
      Heuristic mapping from Ollama's free-text error message to a framework LLMException.ErrorType. Conservative — falls back to empty when the message doesn't match a known phrase so the HTTP-status fallback can still classify.

      Public via the SPI contract; the framework doesn't have Ollama-native "codes" to map (Ollama doesn't define any), so this exists primarily to satisfy the interface and to allow direct heuristic testing. Callers pass the message text.

      Specified by:
      mapErrorType in interface ProviderErrorMapper
      Parameters:
      providerCode - native code (e.g. "context_length_exceeded")
      Returns:
      matching LLMException.ErrorType, or Optional.empty() if the mapper has no opinion