siyuan-note/siyuan · warning

AI editor action must not be empty

Error message

AI editor action must not be empty

What it means

SaveAIEditorAction persists an AI editor action (custom prompt action for the editor). It rejects a nil action or one where both Name and Action are empty, since such an entry would be meaningless and unusable in the UI. This is a pure input-validation guard before any storage work.

Solutions

  1. Provide a non-empty `name` and/or `action` prompt text in the request payload
  2. Validate the payload client-side before POSTing (check at least one of name/action is non-empty)
  3. If updating an existing action, load it first via the list API and modify fields rather than sending a bare {id}

Example fix

// before
fetchPost("/api/ai/editor/action/save", { id: existing.id })
// after
if (!existing.name && !existing.action) throw new Error("name or action is required")
fetchPost("/api/ai/editor/action/save", { id: existing.id, name: existing.name, action: existing.action })
Defensive patterns

Strategy: validation

Validate before calling

if (!action || (!action.name && !action.action)) {
  throw new Error("AI editor action requires a non-empty name or action");
}

Type guard

const isValidAction = (a) => !!a && (typeof a.name === "string" && a.name.trim() !== "" || typeof a.action === "string" && a.action.trim() !== "");

Try / catch

try {
  await fetchPost("/api/ai/editor/action/save", action);
} catch (e) {
  if (e.message.includes("must not be empty")) showMsg("Name or action prompt is required");
}

Prevention

When it happens

Trigger: Calling SaveAIEditorAction (saveAIEditorActionContract API) with a null/empty body, or a JSON payload like {"id":"..."} with no name and no action text; an empty-string Name and Action after client-side trimming.

Common situations: Plugin or script calling the API with a partially built action object; frontend form submitted with all fields blank; JSON unmarshalling producing a zero-value struct.

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/c8516b070ebbce4b. Report an issue: GitHub.

Appendix: source

Thrown at kernel/model/ai_editor.go:72

func GetAIEditorActions() (ret []*AIEditorAction, err error) {
	waitForSyncingStorages()
	aiEditorActionsLock.Lock()
	defer aiEditorActionsLock.Unlock()

	data, err := loadAIEditorActions()
	if err != nil {
		return nil, err
	}
	if err = migrateLegacyAIEditorActions(data, !util.ReadOnly); err != nil {
		return nil, err
	}
	return data.Actions, nil
}

func SaveAIEditorAction(action *AIEditorAction) (ret *AIEditorAction, err error) {
	if action == nil || (action.Name == "" && action.Action == "") {
		return nil, errors.New("AI editor action must not be empty")
	}
	if action.ID != "" && !ast.IsNodeIDPattern(action.ID) {
		return nil, errors.New("invalid AI editor action ID")
	}

	waitForSyncingStorages()
	aiEditorActionsLock.Lock()
	defer aiEditorActionsLock.Unlock()

	data, err := loadAIEditorActions()
	if err != nil {
		return nil, err
	}
	if err = migrateLegacyAIEditorActions(data, true); err != nil {
		return nil, err
	}

	ret = &AIEditorAction{

View on GitHub (pinned to 9f775e8a12)