siyuan-note/siyuan · error

create AI editor actions directory failed: %w

Error message

create AI editor actions directory failed: %w

What it means

saveAIEditorActions (kernel/model/ai_editor.go:193) first ensures the storage directory <workspace>/data/storage/ai/editor exists via os.MkdirAll(0755) before writing actions.json. If directory creation fails, the raw OS error is wrapped with this message and the save (create, update, or delete of any AI editor action) is aborted. It is purely an environment/permissions failure.

Source

Thrown at kernel/model/ai_editor.go:193

			return nil, errors.New("invalid AI editor action data")
		}
		if _, ok := ids[action.ID]; ok {
			return nil, fmt.Errorf("duplicate AI editor action ID [%s]", action.ID)
		}
		ids[action.ID] = struct{}{}
	}
	return ret, nil
}

func saveAIEditorActions(data *aiEditorActionsData) (err error) {
	data.Version = aiEditorActionsVersion
	if data.Actions == nil {
		data.Actions = []*AIEditorAction{}
	}

	dirPath := filepath.Dir(aiEditorActionsPath())
	if err = os.MkdirAll(dirPath, 0755); err != nil {
		return fmt.Errorf("create AI editor actions directory failed: %w", err)
	}
	bytes, err := gulu.JSON.MarshalIndentJSON(data, "", "  ")
	if err != nil {
		return fmt.Errorf("marshal AI editor actions failed: %w", err)
	}
	if err = filelock.WriteFile(aiEditorActionsPath(), bytes); err != nil {
		return fmt.Errorf("write AI editor actions failed: %w", err)
	}
	return nil
}

func migrateLegacyAIEditorActions(data *aiEditorActionsData, persist bool) (err error) {
	localStorage := GetLocalStorage()
	legacyRaw, ok := localStorage[legacyAIEditorActionsStorageKey]
	if !ok {
		return nil
	}

View on GitHub (pinned to afa823b6b4)

Solutions

  1. Check that the SiYuan process can create dirs under <workspace>/data/storage (fix ownership/modes with chown/chmod)
  2. Remove any regular file occupying the ai/editor path components so directories can be created
  3. Verify the workspace volume is mounted read-write and has free space
  4. If the workspace is intentionally read-only, stop trying to save actions — ReadOnly mode cannot persist them
Defensive patterns

Strategy: try-catch

Validate before calling

dir := filepath.Join(util.DataDir, "storage", "ai", "editor")
if err := os.MkdirAll(dir, 0755); err != nil {
    return fmt.Errorf("workspace not writable at %s: %w", dir, err)
}
// only then call SaveAIEditorAction / RemoveAIEditorAction

Try / catch

_, err := model.SaveAIEditorAction(action)
if err != nil && strings.HasPrefix(err.Error(), "create AI editor actions directory failed") {
    // fix ownership/modes on <workspace>/data/storage or remount read-write, then retry
    reportWorkspaceNotWritable(err)
    return
}

Prevention

When it happens

Trigger: MkdirAll fails on: permission denied somewhere along data/storage/ai/editor, a read-only filesystem, a path component that exists as a regular file (e.g. a file named 'ai' or 'editor'), or a full/broken disk. Also occurs when the kernel runs in ReadOnly mode against a locked-down workspace.

Common situations: Workspace restored from an archive that lost directory permissions or changed ownership; workspace on a read-only mount or a drive removed mid-session; a stray file named 'editor' or 'ai' blocking the path; sandboxed/containerized kernels without write access to the data dir.

Related errors


AI-assisted analysis of siyuan-note/siyuan@afa823b6b4 (2026-08-18). Data as JSON: /api/errors/0c1b3457c7cb1d42. Report an issue: GitHub.