siyuan-note/siyuan · error

AI editor action not found

Error message

AI editor action not found

What it means

SaveAIEditorAction performs an update when the action has an ID: it searches the stored action list for a matching ID and replaces it. If no stored action has that ID, the update target is missing and this error is returned instead of silently creating a duplicate.

Source

Thrown at kernel/model/ai_editor.go:108

	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 8641553a1f)

Solutions

  1. Re-fetch the current action list (getAIEditorActions) and retry with a live ID
  2. If the action was intentionally new, omit the ID to create it instead of updating
  3. Confirm the kernel is running against the workspace that contains the action

Example fix

// before
await fetchPost('/api/ai/saveAIEditorAction', {id: staleID, name: 'X', action: 'Y'})
// after
const {data} = await fetchPost('/api/ai/getAIEditorActions', {})
if (data.actions.some(a => a.id === staleID)) {
    await fetchPost('/api/ai/saveAIEditorAction', {id: staleID, name: 'X', action: 'Y'})
}
Defensive patterns

Strategy: try-catch

Validate before calling

const exists = (await fetchPost('/api/ai/getAIEditorActions', {})).data.actions.some(a => a.id === id); if (!exists) { /* create without id instead */ }

Try / catch

try { await saveAction({id, ...}) } catch (e) { if (e.message === 'AI editor action not found') { await refreshActions(); /* recreate or surface conflict */ } }

Prevention

When it happens

Trigger: Calling SaveAIEditorAction with an ID that is syntactically valid but does not exist in the persisted actions list (action deleted elsewhere, stale client cache, wrong workspace).

Common situations: Two clients/sessions where one deleted the action; client retrying an update after the action was removed; pointing the kernel at a different workspace than the one holding the action.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


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