fish2018/pansou · error
加载站点配置失败
Error message
加载站点配置失败: %v
What it means
This error wraps any failure from GyingPlugin.loadConfig() during plugin initialization (Initialize). loadConfig reads the plugin's JSON config file (p.configPath()), and if the file exists but cannot be read (permissions, I/O error) or fails to json.Unmarshal (corrupt/invalid JSON, wrong schema), that error is wrapped as '加载站点配置失败: %v'. A missing file is NOT an error (it returns nil and defaults are used).
Solutions
- Open the config file at p.configPath() and fix any JSON syntax errors (validate with jq or a JSON linter).
- Check file permissions/ownership; ensure the process user can read the file (chmod 644 / chown).
- If the config is corrupt or from an incompatible version, move it aside and let the plugin recreate defaults on next start.
- Check the wrapped '%v' detail in the log to distinguish read errors from parse errors, then fix accordingly.
Example fix
// before (corrupt config)
{"baseURL": https://example.com,} // invalid JSON -> 加载站点配置失败
// after
{"baseURL": "https://example.com"} // valid JSON, loads fine Defensive patterns
Strategy: validation
Validate before calling
func isConfigLoadable(path string) error {
f, err := os.Open(path)
if err != nil { if os.IsNotExist(err) { return nil }; return err }
defer f.Close()
data, err := io.ReadAll(f)
if err != nil { return err }
var v map[string]any
return json.Unmarshal(data, &v)
}
// run before plugin Initialize; on error, repair or remove the config file Try / catch
if err := plugin.Initialize(ctx); err != nil {
if strings.Contains(err.Error(), "加载站点配置失败") {
os.Rename(cfgPath, cfgPath+".corrupt") // quarantine, restart with defaults
}
return err
} Prevention
- Validate the plugin config JSON with a linter after every manual edit.
- Never hand-edit config while the app is running (it may overwrite or race).
- Back up the config file before upgrading the plugin version.
- Ensure the process user owns/can read the storage directory.
When it happens
Trigger: Initialize() calls p.loadConfig() after creating the storage directory; it fails when the config file at configPath() exists but is unreadable (permission denied, disk I/O) or contains invalid JSON / unexpected field types that json.Unmarshal rejects.
Common situations: Config file truncated by a crash or full disk; hand-edited config with syntax errors (trailing comma, unquoted string); config written by an older plugin version whose schema no longer unmarshals into the current struct (type changed e.g. number -> string); file owned by another user after running the app with different privileges.
Understand the failure class
Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/608b9bfafb96cc21.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/gying/gying.go:788
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()
}()
// 启动定期清理任务
go p.startCleanupTask()
// 启动session保活任务(防止session超时)
go p.startSessionKeepAlive()
View on GitHub (pinned to beaa561337)