usememos/memos · error

AI provider capability unsupported

Error message

AI provider capability unsupported

What it means

Sentinel error ai.ErrCapabilityUnsupported indicating the requested AI provider exists but does not support the capability being requested (as opposed to ErrProviderNotFound for a bad ID, or the STT/audio-LLM-specific sentinels). Compare with errors.Is rather than string matching.

Source

Thrown at internal/ai/errors.go:9

package ai

import "github.com/pkg/errors"

var (
	// ErrProviderNotFound indicates that a requested provider ID does not exist.
	ErrProviderNotFound = errors.New("AI provider not found")
	// ErrCapabilityUnsupported indicates that the provider does not support the requested capability.
	ErrCapabilityUnsupported = errors.New("AI provider capability unsupported")
	// ErrSTTNotSupported indicates that the provider does not have a dedicated
	// speech-to-text endpoint. Use the audiollm package for multimodal audio
	// understanding when this is returned.
	ErrSTTNotSupported = errors.New("provider does not support speech-to-text capability")
	// ErrAudioLLMNotSupported indicates that the provider does not have a
	// multimodal-audio LLM available in this codebase.
	ErrAudioLLMNotSupported = errors.New("provider does not support multimodal audio capability")
)

View on GitHub (pinned to 14d757ce1f)

Solutions

  1. Switch the AI settings to a provider that supports the capability you are invoking (for speech-to-text see the dedicated STT providers; for multimodal audio see the audiollm path).
  2. Check errors.Is(err, ai.ErrCapabilityUnsupported) and route the user to a supported provider or a graceful 'unsupported' UI state.
  3. Review the provider capability matrix in the ai package/internal config and align the requested capability with a listed provider.

Example fix

// before
res, err := svc.Transcribe(ctx, req) // opaque error

// after
res, err := svc.Transcribe(ctx, req)
if err != nil {
  if errors.Is(err, ai.ErrCapabilityUnsupported) {
    return status.Errorf(codes.InvalidArgument, "configured AI provider lacks this capability; pick another provider")
  }
  return err
}
Defensive patterns

Strategy: type-guard

Validate before calling

// Go — check capability support before requesting it
caps, ok := ai.ProviderCapabilities(providerID)
if !ok {
  return ai.ErrProviderNotFound
}
if !caps.Has(ai.CapSTT) {
  return status.Errorf(codes.InvalidArgument, "provider %q cannot transcribe; select an STT-capable provider", providerID)
}

Type guard

// Go
func isCapabilityUnsupported(err error) bool {
  return errors.Is(err, ai.ErrCapabilityUnsupported)
}

Try / catch

res, err := svc.Invoke(ctx, req)
if err != nil {
  switch {
  case errors.Is(err, ai.ErrCapabilityUnsupported):
    return status.Errorf(codes.InvalidArgument, "AI provider lacks this capability")
  case errors.Is(err, ai.ErrProviderNotFound):
    return status.Errorf(codes.NotFound, "AI provider not found")
  }
  return err
}

Prevention

When it happens

Trigger: Calling the ai package's capability factory with a provider ID that exists but lacks the requested capability — e.g., asking a text-only provider for STT or multimodal audio, or a provider family whose driver implements one capability only. The dispatch layer returns this sentinel before constructing a client.

Common situations: Mixing provider types in AI settings (pointing STT at a chat-only provider); upgrading/downgrading where a capability was added or removed per provider; custom OpenAI-compatible endpoints that only proxy chat completions.

Related errors


AI-assisted analysis of usememos/memos@14d757ce1f (2026-08-15). Data as JSON: /api/errors/b6ee9a71fa2946fa. Report an issue: GitHub.