apache/answer · error
update site info failed: %w
Error message
update site info failed: %w
What it means
Returned by defaultLoginConfig in internal/cli/config.go when x.ID(loginSiteInfo.ID).Cols("content").Update(loginSiteInfo) fails while persisting the modified allow_password_login content JSON back to the site_info table. The SELECT succeeded and the row exists, so this is a write-side failure: constraint violation, lost connection, read-only replica, or schema mismatch on the content column.
Source
Thrown at internal/cli/config.go:88
func defaultLoginConfig(x *xorm.Engine) (err error) {
fmt.Println("set default login config")
loginSiteInfo := &entity.SiteInfo{
Type: constant.SiteTypeLogin,
}
exist, err := x.Get(loginSiteInfo)
if err != nil {
return fmt.Errorf("get config failed: %w", err)
}
if exist {
var content map[string]any
_ = json.Unmarshal([]byte(loginSiteInfo.Content), &content)
content["allow_password_login"] = true
dataByte, _ := json.Marshal(content)
loginSiteInfo.Content = string(dataByte)
_, err = x.ID(loginSiteInfo.ID).Cols("content").Update(loginSiteInfo)
if err != nil {
return fmt.Errorf("update site info failed: %w", err)
}
}
return nil
}
func deactivatePlugin(x *xorm.Engine, pluginSlugName string) (err error) {
fmt.Printf("try to deactivate plugin: %s\n", pluginSlugName)
item := &entity.Config{Key: constant.PluginStatus}
exist, err := x.Get(item)
if err != nil {
return fmt.Errorf("get config failed: %w", err)
}
if !exist {
return nil
}
pluginStatusMapping := make(map[string]bool)View on GitHub (pinned to 3b9f137061)
Solutions
- Read the wrapped driver error to identify lock timeout vs read-only vs connection loss
- Confirm the database accepts writes (not a read-only replica) and re-run the command
- Retry the operation — transient lock/timeout errors usually succeed on a second attempt
- Check for concurrent writers to the site_info row and coordinate, and verify the content column can hold the new JSON
Defensive patterns
Strategy: retry
Validate before calling
// confirm DB accepts writes before updating
var readonly bool
if _, err := db.SQL("SELECT @@read_only").Get(&readonly); err == nil && readonly {
return errors.New("database is read-only; cannot update site info")
} Try / catch
affected, err := x.ID(loginSiteInfo.ID).Cols("content").Update(loginSiteInfo)
if err != nil {
if isLockTimeout(err) {
time.Sleep(2 * time.Second)
affected, err = x.ID(loginSiteInfo.ID).Cols("content").Update(loginSiteInfo)
}
if err != nil {
return fmt.Errorf("update site info failed: %w", err)
}
} Prevention
- Retry idempotent updates to survive transient lock timeouts
- Keep the DB session short between Get and Update to avoid idle timeouts
- Point write operations at the primary, never a read replica
- Serialize concurrent site-config updates with a lock or version column
When it happens
Trigger: The UPDATE statement fails due to DB connection loss between Get and Update, a read-only database/replica, a lock timeout on the site_info row held by another transaction, or the content column type/length rejecting the marshaled JSON.
Common situations: Concurrent admin sessions updating site settings at the same time; running the CLI against a read replica; upgrading where content column was narrowed; long-running session that hit an idle timeout before the Update executed.
Related errors
- get config failed: %w
- update plugin status failed: %w
- %s failed: %s
- sync version failed: %v
- update site info failed: %w
AI-assisted analysis of apache/answer@3b9f137061 (2026-09-05).
Data as JSON: /api/errors/b51ce4bff635df0e.
Report an issue: GitHub.