siyuan-note/siyuan · error

AI editor input is empty

Error message

AI editor input is empty

What it means

After resolving provider, model, and editing config, NewAIEditorChatStream builds the prompt via BuildAIEditorPrompt(input, action). If the trimmed prompt is empty — because the caller passed an empty input, the referenced block IDs yielded no content, or the action template produced nothing — SiYuan refuses to send a useless request to the model and throws this error.

Solutions

  1. Pass non-empty `input` text or valid `ids` of existing blocks with content
  2. Verify the block IDs exist: fetch them first (e.g. via /api/filetree/getDoc) before calling the AI editor endpoint
  3. Check the action/prompt template — fix or re-select an action that produces non-empty prompt text
  4. Trim-guard on the client: refuse to invoke AI editing when the selection is empty

Example fix

// before
NewAIEditorChatStream(ctx, nil, "", action, history)
// after
if strings.TrimSpace(input) == "" && len(ids) == 0 { return errors.New("nothing selected for AI editing") }
NewAIEditorChatStream(ctx, ids, input, action, history)
Defensive patterns

Strategy: validation

Validate before calling

if strings.TrimSpace(input) === "" && (!ids || ids.length === 0) {
  throw new Error("Provide input text or valid block IDs for AI editing");
}

Try / catch

try {
  await fetchPost("/api/ai/editor/chatStream", payload);
} catch (e) {
  if (e.message.includes("input is empty")) showMsg(window.siyuan.languages.emptyContent);
}

Prevention

When it happens

Trigger: Calling NewAIEditorChatStream (aiEditorChatContract) with input="" and ids=[] (or ids pointing to blocks whose content is empty/unavailable); an action whose prompt template renders to whitespace-only output.

Common situations: Frontend invoking AI on an empty editor or an empty block; stale/invalid block IDs after the document was deleted or IDs were changed; a custom AI action whose template no longer matches the supplied input.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at kernel/model/ai.go:176

	}

	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")
	}

	messages := buildAIEditorMessages(prompt, history, editing.MaxHistoryMessages)

	req := openai.ChatCompletionRequest{
		Model:               m.Name,
		MaxCompletionTokens: editing.MaxCompletionTokens,
		Temperature:         float32(editing.Temperature),
		Messages:            messages,
		Stream:              true,
	}
	streamCtx, cancel := context.WithCancel(ctx)
	streamCtx = util.ContextWithOpenAIResponsesBaseURL(streamCtx, prov.BaseURL)
	requestTimeout := time.Duration(prov.RequestTimeout) * time.Second
	requestTimer, requestTimerDone := startAIEditorCancelTimer(requestTimeout, cancel)
	client := util.NewOpenAIClientWithModel(prov.APIKey, prov.BaseURL, m.Name, ResolveAIProviderHeaders(prov))
	completionStream, err := util.CreateOpenAICompletionStream(streamCtx, client, prov.Protocol, req, nil)
	requestTimedOut := stopAIEditorCancelTimer(requestTimer, requestTimerDone)
	if requestTimedOut {
		err = errors.New("AI editor request timeout")

View on GitHub (pinned to 9f775e8a12)