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

  1. Open the config file at p.configPath() and fix any JSON syntax errors (validate with jq or a JSON linter).
  2. Check file permissions/ownership; ensure the process user can read the file (chmod 644 / chown).
  3. If the config is corrupt or from an incompatible version, move it aside and let the plugin recreate defaults on next start.
  4. 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

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)