{"record":{"id":"78ed2d1bfefa8691","repo":"siyuan-note/siyuan","slug":"create-plugin-dir-s-failed-s","errorCode":null,"errorMessage":"create plugin dir [%s] failed: %s","messagePattern":"create plugin dir \\[(.+?)\\] failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/plugin/plugin.go","lineNumber":270,"sourceCode":"\tp.updateState(PluginStateError)\n}\n\n// start creates the goja runtime, injects sandbox globals, and evaluates kernel.js.\nfunc (p *KernelPlugin) start() (err error) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\terr = fmt.Errorf(\"goja panic during start: %v\", r)\n\t\t}\n\t\tif err != nil {\n\t\t\tp.error()\n\t\t}\n\t}()\n\n\tp.updateState(PluginStateLoading)\n\n\tbaseDir := filepath.Join(util.DataDir, \"storage\", \"petal\", p.Name)\n\tif err := os.MkdirAll(baseDir, 0755); err != nil {\n\t\treturn fmt.Errorf(\"create plugin dir [%s] failed: %s\", baseDir, err)\n\t}\n\n\tif runtimeErr := p.InitRuntime(); runtimeErr != nil {\n\t\treturn fmt.Errorf(\"start runtime: %v\", runtimeErr)\n\t}\n\n\tif subscribeErr := p.subscribeEventHandlers(); subscribeErr != nil {\n\t\treturn fmt.Errorf(\"subscribe plugin events: %v\", subscribeErr)\n\t}\n\n\tp.onLoad()\n\tp.updateState(PluginStateRunning)\n\tp.onRunning()\n\n\tp.bus.Publish(EventBusTopicRuntime, createEventMessage(\"start\", nil))\n\n\tlogging.LogDebugf(\"[plugin:%s] started\", p.Name)\n\treturn","sourceCodeStart":252,"sourceCodeEnd":288,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/plugin/plugin.go#L252-L288","documentation":"At the beginning of plugin startup, the kernel creates the plugin's data directory at `data/storage/petal/<pluginName>` with `os.MkdirAll`. If that fails (permissions, disk full, path occupied by a file), startup aborts with `create plugin dir [<path>] failed: <reason>`. The plugin never reaches runtime initialization.","triggerScenarios":"os.MkdirAll failing because a file already exists at the plugin's directory path, the data directory is read-only, disk quota is exhausted, or the plugin name contains characters invalid for the host filesystem.","commonSituations":"Running SiYuan from a read-only mount or restricted workspace directory, an OS-level file locking the path, a plugin name with `/` or reserved characters creating a bad path, or full disk on mobile devices.","solutions":["Check whether a FILE exists at the reported path — remove or rename it so a directory can be created","Verify write permissions on `data/storage/petal/` and that the disk is not full","Ensure the workspace directory is writable by the SiYuan process user","Check the plugin name for illegal path characters; update/uninstall the plugin if so"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// before starting the plugin, check the path is creatable\nif info, err := os.Stat(filepath.Join(util.DataDir, \"storage\", \"petal\", name)); err == nil && !info.IsDir() {\n    return fmt.Errorf(\"%s exists as a file; remove it so the plugin dir can be created\", name)\n}","typeGuard":null,"tryCatchPattern":"if err := os.MkdirAll(dir, 0755); err != nil { return fmt.Errorf(\"check disk space and permissions on %s: %w\", dir, err) }","preventionTips":["Keep the workspace data directory writable by the kernel process","Watch disk space, especially on mobile devices","Never manually place a file where data/storage/petal/<plugin> should be","Use filesystem-safe plugin names (no slashes or reserved characters)"],"tags":["filesystem","mkdir","permissions","plugin-lifecycle"],"backgroundTag":"file-write-failed","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}