usememos/memos · error
OpenAI API key is required
Error message
OpenAI API key is required
What it means
Returned by openai.New (internal/ai/stt/openai) when ai.ProviderConfig.APIKey is the empty string. The OpenAI-compatible SDK client is constructed with WithAPIKey(cfg.APIKey), and an empty key would only fail later at the HTTP layer with 401s, so construction fails fast instead.
Source
Thrown at internal/ai/stt/openai/openai.go:34
"github.com/usememos/memos/internal/ai"
"github.com/usememos/memos/internal/ai/stt"
)
const defaultEndpoint = "https://api.openai.com/v1"
// Transcriber implements stt.Transcriber for OpenAI-compatible STT endpoints.
type Transcriber struct {
client openaisdk.Client
}
// New constructs a Transcriber from a provider config.
func New(cfg ai.ProviderConfig, options stt.Options) (*Transcriber, error) {
endpoint, err := normalizeEndpoint(cfg.Endpoint)
if err != nil {
return nil, err
}
if cfg.APIKey == "" {
return nil, errors.New("OpenAI API key is required")
}
return &Transcriber{
client: openaisdk.NewClient(
openaioption.WithAPIKey(cfg.APIKey),
openaioption.WithBaseURL(endpoint),
openaioption.WithHTTPClient(options.HTTPClient),
),
}, nil
}
// Transcribe sends the audio to /audio/transcriptions.
func (t *Transcriber) Transcribe(ctx context.Context, req stt.Request) (*stt.Response, error) {
if strings.TrimSpace(req.Model) == "" {
return nil, errors.New("model is required")
}
if req.Audio == nil {
return nil, errors.New("audio is required")
}View on GitHub (pinned to 14d757ce1f)
Solutions
- Set the API key in the AI provider settings for the OpenAI-compatible provider and retry.
- Verify the secret actually reaches the process (container env, secret store) — reference by name, never log it.
- For local no-auth endpoints, pass any non-empty placeholder key if your setup allows it.
- Confirm you selected the right provider type; a dedicated STT provider may be the wrong choice (see ai.ErrSTTNotSupported).
Example fix
// before
cfg := ai.ProviderConfig{Endpoint: "https://api.openai.com/v1"}
t, err := openai.New(cfg, opts) // err: OpenAI API key is required
// after
cfg := ai.ProviderConfig{Endpoint: "https://api.openai.com/v1", APIKey: os.Getenv("MEMOS_OPENAI_API_KEY")}
if cfg.APIKey == "" {
return errors.New("MEMOS_OPENAI_API_KEY not set")
}
t, err := openai.New(cfg, opts) Defensive patterns
Strategy: validation
Validate before calling
// Go — gate on the key by name, never log it
if strings.TrimSpace(cfg.APIKey) == "" {
return errors.New("AI provider API key is not configured (check provider settings / injected secret)")
}
_, err := openai.New(cfg, opts) Try / catch
t, err := openai.New(cfg, opts)
if err != nil {
if strings.Contains(err.Error(), "API key is required") {
return status.Errorf(codes.FailedPrecondition, "AI provider not configured: add an API key in settings")
}
return err
} Prevention
- Validate provider config (key present, endpoint normalized) at settings-save time.
- Inject secrets via env/secret store; verify presence at boot with a non-empty assert.
- For no-auth local endpoints, require an explicit placeholder key in config rather than empty.
When it happens
Trigger: Creating the OpenAI STT transcriber with a provider config whose APIKey was never populated — e.g., the Memos AI provider settings saved without a key, or the env/source feeding ProviderConfig returned an empty string. Happens on the first transcription attempt or at provider construction.
Common situations: Fresh AI provider setup where the key field was left blank; secret env var (OPENAI_API_KEY) not injected into the container; using a local OpenAI-compatible server (whisper.cpp, vLLM) that needs no auth but the code path still requires a non-empty key string.
Related errors
- AI provider capability unsupported
- SMTP host is required
- SMTP port must be between 1 and 65535
- from email is required
- SMTP server does not support STARTTLS
AI-assisted analysis of usememos/memos@14d757ce1f (2026-08-15).
Data as JSON: /api/errors/98bf6b20ecff4eef.
Report an issue: GitHub.