fish2018/pansou · error
创建存储目录失败
Error message
创建存储目录失败: %v
What it means
Raised at plugin/gying.go:783 during plugin initialization. The plugin determines StorageDir = <cachePath>/gying_users and calls os.MkdirAll(StorageDir, 0755); if directory creation fails (permission denied, path is a file, unwritable parent), the OS error is wrapped with this message and initialization aborts.
Solutions
- Read the wrapped %v error to confirm the cause (permission denied vs not-a-directory).
- Ensure the cache directory's parent exists and is writable: mkdir -p ./cache && chmod 755 ./cache.
- If ./cache is a regular file, remove or rename it so it can be a directory.
- Configure cachePath to a writable location and rerun.
- In containers, mount a writable volume at the cache path.
Example fix
// before os.Setenv/... cachePath = "/ro-mount/cache" // read-only mount // after cachePath = "/var/cache/app" // writable location; mkdir -p /var/cache/app
Defensive patterns
Strategy: validation
Validate before calling
dir := filepath.Join(cachePath, "gying_users")
if info, err := os.Stat(filepath.Dir(dir)); err != nil || !info.IsDir() { return fmt.Errorf("cache parent missing: %s", filepath.Dir(dir)) }
if f, err := os.CreateTemp(filepath.Dir(dir), ".w*"); err != nil { return fmt.Errorf("cache path not writable") } else { f.Close(); os.Remove(f.Name()) } Try / catch
if err := plugin.Init(); err != nil {
var pe *fs.PathError
if errors.As(err, &pe) && errors.Is(pe.Err, syscall.EACCES) {
log.Printf("cannot create storage dir (permissions): %v", err)
}
return err
} Prevention
- Ensure ./cache (or the configured cachePath) exists and is writable before starting the app.
- Never place a regular file where the cache directory is expected.
- In containers, mount a writable volume for the cache path and run as a user with write access.
When it happens
Trigger: Plugin Init with cachePath unset (defaults to ./cache) or set to an unwritable/nonexistent location; MkdirAll fails because a parent component is a file, or the process lacks write permission on the parent.
Common situations: Running the app in a read-only container or working directory; deploying as a non-root user while cachePath points to a root-owned path; ./cache accidentally replaced by a regular file.
Understand the failure class
Background: mkdir permission denied (EACCES): failed to create directory errors explained — this error's family across 32 libraries.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/08a3a7a73a15e6e4.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/gying/gying.go:783
return baseURL, nil
}
// Initialize 实现 InitializablePlugin 接口,延迟初始化插件
func (p *GyingPlugin) Initialize() error {
if p.initialized {
return nil
}
// 初始化存储目录路径
cachePath := os.Getenv("CACHE_PATH")
if cachePath == "" {
cachePath = "./cache"
}
StorageDir = filepath.Join(cachePath, "gying_users")
// 初始化存储目录
if err := os.MkdirAll(StorageDir, 0755); err != nil {
return fmt.Errorf("创建存储目录失败: %v", err)
}
// 加载站点配置
if err := p.loadConfig(); err != nil {
return fmt.Errorf("加载站点配置失败: %v", err)
}
// 加载所有用户到内存
p.loadAllUsers()
// 异步初始化默认账户(不阻塞启动)
go func() {
// 延迟1秒,等待主程序完全启动
time.Sleep(1 * time.Second)
p.initDefaultAccounts()
}()
// 启动定期清理任务View on GitHub (pinned to beaa561337)