{"record":{"id":"28cbc5db3d2c437d","repo":"fish2018/pansou","slug":"w-28cbc5","errorCode":null,"errorMessage":"创建存储目录失败: %w","messagePattern":"创建存储目录失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/panlian/panlian.go","lineNumber":532,"sourceCode":"}\n\nfunc (p *PanlianPlugin) Description() string {\n\treturn Description\n}\n\nfunc (p *PanlianPlugin) Initialize() error {\n\tif p.initialized {\n\t\treturn nil\n\t}\n\n\tcachePath := os.Getenv(\"CACHE_PATH\")\n\tif cachePath == \"\" {\n\t\tcachePath = \"./cache\"\n\t}\n\tstorageDir = filepath.Join(cachePath, \"panlian_users\")\n\n\tif err := os.MkdirAll(storageDir, 0o755); err != nil {\n\t\treturn fmt.Errorf(\"创建存储目录失败: %w\", err)\n\t}\n\tif err := p.loadConfig(); err != nil {\n\t\treturn fmt.Errorf(\"加载配置失败: %w\", err)\n\t}\n\tp.loadAllUsers()\n\tp.initialized = true\n\treturn nil\n}\n\nfunc (p *PanlianPlugin) RegisterWebRoutes(router *gin.RouterGroup) {\n\tgroup := router.Group(\"/panlian\")\n\tgroup.GET(\"/:param\", p.handleManagePage)\n\tgroup.POST(\"/:param\", p.handleManagePagePOST)\n}\n\nfunc (p *PanlianPlugin) Search(keyword string, ext map[string]interface{}) ([]model.SearchResult, error) {\n\tresult, err := p.SearchWithResult(keyword, ext)\n\tif err != nil {","sourceCodeStart":514,"sourceCodeEnd":550,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/panlian/panlian.go#L514-L550","documentation":"PanlianPlugin.Initialize creates the per-user storage directory <cachePath>/panlian_users via os.MkdirAll; if that fails (permissions, read-only FS, path occupied by a file) it returns '创建存储目录失败' wrapping the OS error. This aborts plugin initialization.","triggerScenarios":"os.MkdirAll(storageDir, 0o755) fails because cachePath is unwritable, its parent is a regular file, the disk is full, or the process lacks write permission on the cache path.","commonSituations":"Running in a read-only container or systemd unit with ProtectSystem=strict; ./cache pre-created by root then app run as another user; cachePath mistakenly set to a file path; disk quota exceeded.","solutions":["Check that the configured cache path (default ./cache) exists as a directory and is writable by the process user: ls -ld ./cache.","Fix permissions (chown/chmod) or run from a working directory where a writable ./cache can be created.","Point the plugin's cachePath config at a persistent writable directory (e.g. /var/lib/yourapp/cache).","Remove any regular file occupying the panlian_users path."],"exampleFix":"// before\ncachePath = \"./cache\" // read-only in container\n// after\ncachePath = \"/var/lib/mediasearch/cache\" // writable volume","handlingStrategy":"validation","validationCode":"import \"os\"\n\nfunc dirWritable(path string) bool {\n    if fi, err := os.Stat(path); err == nil && !fi.IsDir() {\n        return false\n    }\n    probe := filepath.Join(path, \".write_probe\")\n    if err := os.WriteFile(probe, nil, 0o644); err != nil {\n        return false\n    }\n    os.Remove(probe)\n    return true\n}\n// call before Initialize: dirWritable(\"./cache\")","typeGuard":null,"tryCatchPattern":"if err := plugin.Initialize(cachePath, cfg); err != nil {\n    if strings.Contains(err.Error(), \"创建存储目录失败\") {\n        log.Fatalf(\"cache dir unusable: %v — set cachePath to a writable dir\", err)\n    }\n    return err\n}","preventionTips":["Configure cachePath to a guaranteed-writable volume, not the process CWD.","Check container/systemd read-only mounts (ProtectSystem, readOnlyRootFilesystem) before deploying.","Ensure the cache dir is owned by the same user the service runs as.","Pre-create the directory in deployment scripts with correct ownership."],"tags":["filesystem","mkdir","initialization","permissions"],"backgroundTag":"mkdir-permission-denied","analyzedSha":"beaa56133755a548ebc51b090b3816e2ae044aa6","analyzedAt":"2026-09-07T00:31:18.025Z","contentChangedAt":"2026-09-07T00:31:18.025Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}