fish2018/pansou · error
迁移旧站点配置失败
Error message
迁移旧站点配置失败: %w
What it means
Thrown at plugin/gying.go:701 during config load/upgrade. When the stored baseURL matches a legacy URL form (isLegacyGyingBaseURL), the plugin rewrites it to DefaultGyingBaseURL and calls p.saveConfig; if persisting the migrated value fails, the write error is wrapped with this message.
Solutions
- Inspect the wrapped %w cause to see the actual save failure (permission, path, disk).
- Ensure the plugin's config/cache directory exists and is writable by the process user (chmod/chown as needed).
- Manually update the stored baseURL to the current default so migration is skipped on next start.
- Check for another process holding the config file and retry after freeing it.
Example fix
// before (read-only dir) chmod 555 ./cache // after chmod 755 ./cache && chown $USER ./cache
Defensive patterns
Strategy: try-catch
Validate before calling
// check config dir writability before load
info, err := os.Stat(configDir)
if err != nil || !info.IsDir() { return fmt.Errorf("config dir missing: %s", configDir) }
if err := os.WriteFile(filepath.Join(configDir, ".wtest"), nil, 0644); err != nil { return fmt.Errorf("config dir not writable") }
os.Remove(filepath.Join(configDir, ".wtest")) Try / catch
if err := p.loadConfig(); err != nil {
if strings.Contains(err.Error(), "迁移旧站点配置失败") {
log.Printf("config migration failed, fix permissions on config dir: %v", err)
}
return err
} Prevention
- Keep the plugin's config/cache directory writable by the service user after upgrades.
- Pre-update stored baseURLs to the current default to avoid triggering migration.
- Monitor disk space on the host running the plugin.
When it happens
Trigger: Plugin startup or config load where an old-format baseURL is detected AND saving the new default fails — typically because the config file is read-only, the directory is missing, or disk is full.
Common situations: Upgrading the plugin while running under a read-only filesystem or a user without write permission to the config/cache directory; config file corrupted or locked by another process.
Understand the failure class
Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/bb75140e127847ff.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/gying/gying.go:701
return err
}
var config GyingConfig
if err := json.Unmarshal(data, &config); err != nil {
return err
}
if config.BaseURL == "" {
return nil
}
baseURL, err := normalizeBaseURL(config.BaseURL)
if err != nil {
return err
}
if isLegacyGyingBaseURL(baseURL) {
baseURL = DefaultGyingBaseURL
if err := p.saveConfig(baseURL); err != nil {
return fmt.Errorf("迁移旧站点配置失败: %w", err)
}
}
p.setBaseURL(baseURL)
return nil
}
func (p *GyingPlugin) saveConfig(baseURL string) error {
config := GyingConfig{
BaseURL: baseURL,
UpdatedAt: time.Now(),
}
data, err := json.MarshalIndent(config, "", " ")
if err != nil {
return err
}
return ioutil.WriteFile(p.configPath(), data, 0644)
}View on GitHub (pinned to beaa561337)