siyuan-note/siyuan · error

no AI provider configured

Error message

no AI provider configured

What it means

NewAIEditorChatStream first verifies that at least one AI provider is configured (Conf.AI.HasAnyProvider()); if none is, it returns this error without creating the stream. The editor AI chat feature requires an API provider (e.g. OpenAI-compatible endpoint with key) to be set up in configuration.

Solutions

  1. Open Settings - AI and add at least one AI provider (endpoint + API key)
  2. Verify the configuration file actually contains AI provider entries (Conf.AI.Providers non-empty)
  3. If calling programmatically, check Conf.AI.HasAnyProvider() (or fetch AI config via API) before invoking the editor chat endpoint
  4. Re-enter the API key if an upgrade or config merge dropped it

Example fix

// before
stream, err := model.NewAIEditorChatStream(ctx, ids, input, action, history) // fails: no provider
// after
if !conf.AI.HasAnyProvider() {
    return errors.New("please configure an AI provider in Settings - AI first")
}
stream, err := model.NewAIEditorChatStream(ctx, ids, input, action, history)
Defensive patterns

Strategy: validation

Validate before calling

// before invoking editor AI chat
const aiConf = await fetchPost('/api/ai/...', {});
if (!aiConf || !aiConf.ai || !aiConf.ai.providers || aiConf.ai.providers.length === 0) {
  alert('Please configure an AI provider in Settings - AI first');
  return;
}

Type guard

null

Try / catch

try {
  stream, err := model.NewAIEditorChatStream(ctx, ids, input, action, history)
  if err != nil { return err } // includes "no AI provider configured"
} catch (e) { showAiSetupDialog(); }

Prevention

When it happens

Trigger: Calling the aiEditorChat contract endpoint (editor AI chat) when no AI providers exist in the configuration — empty provider list, fresh install, or providers removed/cleared.

Common situations: Fresh SiYuan install where AI settings were never filled in, API key cleared or config reset, sync restoring a config without AI settings, calling the editor AI API from a plugin/automation on a machine without AI setup.

Understand the failure class

Background: "API key is required" / "API key not found" / "No API key was set": the missing-api-key error family across 16 libraries — this error's family across 16 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/5051fd5d1568a288. Report an issue: GitHub.

Appendix: source

Thrown at kernel/model/ai.go:157

func (stream *AIEditorChatStream) Recv() (response openai.ChatCompletionStreamResponse, err error) {
	timer, timerDone := startAIEditorCancelTimer(stream.idleTimeout, stream.cancel)
	response, err = stream.stream.Recv()
	if stopAIEditorCancelTimer(timer, timerDone) {
		err = errors.New("AI editor stream idle timeout")
	}
	return
}

func (stream *AIEditorChatStream) Close() {
	stream.cancel()
	stream.stream.Close()
}

// NewAIEditorChatStream 创建绑定到编辑器请求生命周期的模型流。
func NewAIEditorChatStream(ctx context.Context, ids []string, input, action string, history []AIEditorMessage) (*AIEditorChatStream, error) {
	if !Conf.AI.HasAnyProvider() {
		return nil, errors.New("no AI provider configured")
	}

	prov, m := Conf.AI.GetEditingModel()
	if nil == prov || nil == m {
		return nil, errors.New("no AI editing model configured")
	}
	editing := Conf.AI.Editing
	if nil == editing {
		return nil, errors.New("no AI editing config")
	}

	if "" == input && 0 < len(ids) {
		input = getBlocksContent(ids)
	}
	prompt := BuildAIEditorPrompt(input, action)
	if "" == strings.TrimSpace(prompt) {
		return nil, errors.New("AI editor input is empty")
	}

View on GitHub (pinned to 9f775e8a12)