{"record":{"id":"0c1b3457c7cb1d42","repo":"siyuan-note/siyuan","slug":"create-ai-editor-actions-directory-failed-w","errorCode":null,"errorMessage":"create AI editor actions directory failed: %w","messagePattern":"create AI editor actions directory failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/ai_editor.go","lineNumber":193,"sourceCode":"\t\t\treturn nil, errors.New(\"invalid AI editor action data\")\n\t\t}\n\t\tif _, ok := ids[action.ID]; ok {\n\t\t\treturn nil, fmt.Errorf(\"duplicate AI editor action ID [%s]\", action.ID)\n\t\t}\n\t\tids[action.ID] = struct{}{}\n\t}\n\treturn ret, nil\n}\n\nfunc saveAIEditorActions(data *aiEditorActionsData) (err error) {\n\tdata.Version = aiEditorActionsVersion\n\tif data.Actions == nil {\n\t\tdata.Actions = []*AIEditorAction{}\n\t}\n\n\tdirPath := filepath.Dir(aiEditorActionsPath())\n\tif err = os.MkdirAll(dirPath, 0755); err != nil {\n\t\treturn fmt.Errorf(\"create AI editor actions directory failed: %w\", err)\n\t}\n\tbytes, err := gulu.JSON.MarshalIndentJSON(data, \"\", \"  \")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"marshal AI editor actions failed: %w\", err)\n\t}\n\tif err = filelock.WriteFile(aiEditorActionsPath(), bytes); err != nil {\n\t\treturn fmt.Errorf(\"write AI editor actions failed: %w\", err)\n\t}\n\treturn nil\n}\n\nfunc migrateLegacyAIEditorActions(data *aiEditorActionsData, persist bool) (err error) {\n\tlocalStorage := GetLocalStorage()\n\tlegacyRaw, ok := localStorage[legacyAIEditorActionsStorageKey]\n\tif !ok {\n\t\treturn nil\n\t}\n","sourceCodeStart":175,"sourceCodeEnd":211,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/afa823b6b4e4f183511e0bc0a3be93caa94c7c97/kernel/model/ai_editor.go#L175-L211","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check that the SiYuan process can create dirs under <workspace>/data/storage (fix ownership/modes with chown/chmod)","Remove any regular file occupying the ai/editor path components so directories can be created","Verify the workspace volume is mounted read-write and has free space","If the workspace is intentionally read-only, stop trying to save actions — ReadOnly mode cannot persist them"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"dir := filepath.Join(util.DataDir, \"storage\", \"ai\", \"editor\")\nif err := os.MkdirAll(dir, 0755); err != nil {\n    return fmt.Errorf(\"workspace not writable at %s: %w\", dir, err)\n}\n// only then call SaveAIEditorAction / RemoveAIEditorAction","typeGuard":null,"tryCatchPattern":"_, err := model.SaveAIEditorAction(action)\nif err != nil && strings.HasPrefix(err.Error(), \"create AI editor actions directory failed\") {\n    // fix ownership/modes on <workspace>/data/storage or remount read-write, then retry\n    reportWorkspaceNotWritable(err)\n    return\n}","preventionTips":["Verify workspace write access after restoring from archives or moving between machines","Keep path components data/, storage/, ai/ as directories — a stray file named 'ai' or 'editor' blocks creation","In read-only deployments, do not expose action-saving UI"],"tags":["ai","filesystem","permissions","io-error"],"backgroundTag":"directory-create-failed","analyzedSha":"afa823b6b4e4f183511e0bc0a3be93caa94c7c97","analyzedAt":"2026-08-18T17:04:10.865Z","schemaVersion":2},"datasetVersion":"2026-08-31T22:30:34.772Z"}