siyuan-note/siyuan · error

AI editor action not found

Error message

AI editor action not found

What it means

When SaveAIEditorAction is called with a non-empty ID, it treats the call as an update: it searches the stored actions for a matching ID and replaces it. If no stored action has that ID, `updated` stays false and SiYuan returns "AI editor action not found" — you cannot 'update' an action that was never created (or was deleted).

Solutions

  1. List current actions (GetAIEditorActions) and confirm the ID exists before updating
  2. If creating is intended, omit the ID so the kernel appends a new action
  3. Refresh the client's cached action list after deletes/sync to avoid stale IDs
  4. Handle the error by falling back to a create (save without ID) if appropriate

Example fix

// before
saveAIEditorAction(&AIEditorAction{ID: staleID, Name: "Renamed"})
// after
actions, _ := GetAIEditorActions()
if !containsID(actions, staleID) { return saveAIEditorAction(&AIEditorAction{Name: "Renamed"}) } // create instead
Defensive patterns

Strategy: validation

Validate before calling

const actions = await fetchPost("/api/ai/editor/action/list", {});
if (!actions.some(a => a.id === id)) throw new Error("Action no longer exists; refresh the list");

Try / catch

try {
  await saveAIEditorAction({ id, ...changes });
} catch (e) {
  if (e.message.includes("not found")) {
    // refresh action list; offer to recreate the action
  }
}

Prevention

When it happens

Trigger: Calling SaveAIEditorAction with a well-formed but nonexistent ID; updating an action that was removed in another session or another synced device; stale IDs cached by a plugin after the action list changed.

Common situations: Race between two clients where one deletes the action while another edits it; plugin holding a stale snapshot of the action list; typo'd ID that happens to match the node-ID pattern.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


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

Appendix: source

Thrown at kernel/model/ai_editor.go:107

	ret = &AIEditorAction{
		ID:     action.ID,
		Name:   action.Name,
		Action: action.Action,
	}
	if ret.ID == "" {
		ret.ID = ast.NewNodeID()
		data.Actions = append(data.Actions, ret)
	} else {
		updated := false
		for i, item := range data.Actions {
			if item.ID == ret.ID {
				data.Actions[i] = ret
				updated = true
				break
			}
		}
		if !updated {
			return nil, errors.New("AI editor action not found")
		}
	}

	if err = saveAIEditorActions(data); err != nil {
		return nil, err
	}
	return ret, nil
}

func RemoveAIEditorAction(id string) (err error) {
	if !ast.IsNodeIDPattern(id) {
		return errors.New("invalid AI editor action ID")
	}

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

View on GitHub (pinned to 9f775e8a12)