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
- Pass non-empty `input` text or valid `ids` of existing blocks with content
- Verify the block IDs exist: fetch them first (e.g. via /api/filetree/getDoc) before calling the AI editor endpoint
- Check the action/prompt template — fix or re-select an action that produces non-empty prompt text
- 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
- Disable AI actions on empty selections in the UI
- Verify block IDs exist before sending them
- Test custom action templates with minimal input
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 editor action must not be empty
- asset data is empty
- assetPath is required for analyze
- at least one asset path or mapping is required
- capability validator unavailable
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)