{"record":{"id":"8ead80ed80db607e","repo":"fish2018/pansou","slug":"v-8ead80","errorCode":null,"errorMessage":"创建存储目录失败: %v","messagePattern":"创建存储目录失败: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/qqpd/qqpd.go","lineNumber":534,"sourceCode":"\tplugin.RegisterGlobalPlugin(p)\n}\n\n// Initialize 实现 InitializablePlugin 接口，延迟初始化插件\nfunc (p *QQPDPlugin) Initialize() error {\n\tif p.initialized {\n\t\treturn nil\n\t}\n\n\t// 初始化存储目录路径\n\tcachePath := os.Getenv(\"CACHE_PATH\")\n\tif cachePath == \"\" {\n\t\tcachePath = \"./cache\"\n\t}\n\tStorageDir = filepath.Join(cachePath, \"qqpd_users\")\n\n\t// 初始化存储目录\n\tif err := os.MkdirAll(StorageDir, 0755); err != nil {\n\t\treturn fmt.Errorf(\"创建存储目录失败: %v\", err)\n\t}\n\n\t// 加载所有用户到内存\n\tp.loadAllUsers()\n\n\t// 启动定期清理任务\n\tgo p.startCleanupTask()\n\n\tp.initialized = true\n\treturn nil\n}\n\n// ============ 插件接口实现 ============\n\n// SkipServiceFilter 返回是否跳过Service层的关键词过滤\n// 注释掉：让Service层来处理过滤，Service层会根据每个链接的标题进行精确过滤\n// func (p *QQPDPlugin) SkipServiceFilter() bool {\n// \treturn true","sourceCodeStart":516,"sourceCodeEnd":552,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/qqpd/qqpd.go#L516-L552","documentation":"QQPDPlugin.Initialize (plugin/qqpd/qqpd.go:534) fails when os.MkdirAll on the '<cachePath>/qqpd_users' directory (default ./cache) returns an error, typically a filesystem permission problem or an unwritable path. Initialization aborts, so the QQPD plugin does not start.","triggerScenarios":"os.MkdirAll(StorageDir, 0755) fails during Initialize — e.g. cachePath resolves to a read-only mount, the process user lacks write permission on the parent directory, a file already exists at the target path, or the disk is full.","commonSituations":"Running the bot as a non-root user whose working directory is not writable, deploying in a read-only Docker container filesystem, or configuring a cachePath pointing to an invalid/mounted read-only volume.","solutions":["Check permissions on the cache directory parent (ls -ld ./cache) and grant write access to the process user","Set the cache path configuration to a writable location (e.g. /var/lib/<app>/cache)","If running in Docker, mount a writable volume at the cache path","Verify the path isn't an existing regular file that blocks directory creation"],"exampleFix":"// before\ncachePath = \"./cache\"\n// after (config)\ncachePath = \"/var/lib/qqpd/cache\"  # plus: chown appuser /var/lib/qqpd","handlingStrategy":"validation","validationCode":"const storageDir = filepath.Join(cachePath, \"qqpd_users\")\nif fi, err := os.Stat(filepath.Dir(storageDir)); err != nil || !fi.IsDir() {\n    return fmt.Errorf(\"cache path %q not writable directory\", filepath.Dir(storageDir))\n}\nif err := os.WriteFile(filepath.Join(filepath.Dir(storageDir), \".probe\"), nil, 0644); err != nil {\n    return fmt.Errorf(\"cache path not writable: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if err := p.Initialize(); err != nil {\n    if strings.Contains(err.Error(), \"创建存储目录失败\") {\n        os.Exit(1) // or fall back to a writable temp dir\n    }\n    return err\n}","preventionTips":["Run the process as a user with write access to the working directory","Mount a writable volume for the cache path in containers","Pre-create the cache directory with correct ownership in deployment scripts","Avoid read-only root filesystems without an explicit writable data mount"],"tags":["filesystem","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"}