syncthing/syncthing · info · svcutil.FatalErr
restart after db reset initiated by rest API
Error message
restart after db reset initiated by rest API
What it means
This is not a failure: it is a deliberately constructed sentinel error passed to s.fatal() by the REST handler for POST /rest/system/reset after the handler has flushed a success response. It instructs the supervised process to exit with svcutil.ExitRestart so the supervisor restarts Syncthing and the just-wiped or reset database is reopened cleanly. Any caller of the reset endpoint should expect the process to terminate by design.
Source
Thrown at lib/api/api.go:1016
// Reset all folders.
for folder := range s.cfg.Folders() {
if err := s.model.ResetFolder(folder); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
s.flushResponse(`{"ok": "resetting database"}`, w)
} else {
// Reset a specific folder, assuming it's supposed to exist.
if err := s.model.ResetFolder(folder); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
s.flushResponse(`{"ok": "resetting folder `+folder+`"}`, w)
}
s.fatal(&svcutil.FatalErr{
Err: errors.New("restart after db reset initiated by rest API"),
Status: svcutil.ExitRestart,
})
}
func (s *service) postSystemShutdown(w http.ResponseWriter, _ *http.Request) {
s.flushResponse(`{"ok": "shutting down"}`, w)
s.fatal(&svcutil.FatalErr{
Err: errors.New("shutdown initiated by rest API"),
Status: svcutil.ExitSuccess,
})
}
func (*service) flushResponse(resp string, w http.ResponseWriter) {
w.Write([]byte(resp + "\n"))
f := w.(http.Flusher)
f.Flush()
}
View on GitHub (pinned to 058bcd7334)
Solutions
- Treat the flushed '{"ok": "resetting..."}' response as the success signal and stop making further API calls until the service restarts.
- Have your supervision wrapper (systemd, docker restart policy, syncthing's own -resume or supervisor) restart the process on the ExitRestart exit status.
- If you only wanted to reset one folder, pass ?folder=<id> and still expect the restart, since the handler always calls s.fatal with ExitRestart.
- Back up index databases before calling reset if you might need the data; reset is destructive.
Defensive patterns
Strategy: validation
Validate before calling
// Before calling reset, confirm you really want a restart:
// POST /rest/system/reset always ends with the process exiting (ExitRestart).
// Validate preconditions (backup taken, no in-flight transfers) first.
resp, err := http.Post(apiURL+"/rest/system/reset", "", nil)
// After reading '{"ok": "resetting..."}', stop calling the API until restart completes. Try / catch
// Not applicable: this is a deliberate process-exit sentinel, not a catchable
// API error. The response body '{"ok": "resetting database"}' is the success signal. Prevention
- Treat POST /rest/system/reset as destructive and terminal for the current process; script the follow-up as wait-for-restart.
- Back up the index database before resetting.
- Wrap automation with a readiness poll (e.g. GET /rest/system/version) after the reset instead of immediate further calls.
When it happens
Trigger: POST /rest/system/reset (with or without ?folder=...) reaching the end of the handler: after ResetAll or model.ResetFolder succeeds and '{"ok": "resetting..."}' has been flushed, s.fatal(&svcutil.FatalErr{Err: errors.New("restart after db reset initiated by rest API"), Status: svcutil.ExitRestart}) is invoked unconditionally.
Common situations: Automation or a GUI script calling the reset endpoint and then being surprised that subsequent REST calls fail because the process exited; expecting an error body instead of the flushed ok JSON followed by process exit.
Related errors
- shutdown initiated by rest API
- exit after upgrade initiated by rest API
- Internal Server Error
- restart initiated by rest API
- no suitable name
AI-assisted analysis of syncthing/syncthing@058bcd7334 (2026-08-15).
Data as JSON: /api/errors/6f68ebd58e15c87d.
Report an issue: GitHub.