syncthing/syncthing · critical
failed to load config: unexpected end of file. Truncated or
Error message
failed to load config: unexpected end of file. Truncated or empty configuration?
What it means
config.Load returned io.EOF, meaning the configuration XML file exists but contains zero bytes or is cut off mid-document. Syncthing refuses to fabricate a config in this case (unlike a missing file, which triggers DefaultConfig generation) because overwriting might destroy a partially-written real config.
Source
Thrown at lib/syncthing/utils.go:102
// LoadConfigAtStartup loads an existing config. If it doesn't yet exist, it
// creates a default one. Otherwise it checks the version, and archives and
// upgrades the config if necessary or returns an error, if the version
// isn't compatible.
func LoadConfigAtStartup(path string, cert tls.Certificate, evLogger events.Logger, allowNewerConfig, skipPortProbing bool) (config.Wrapper, error) {
myID := protocol.NewDeviceID(cert.Certificate[0])
cfg, originalVersion, err := config.Load(path, myID, evLogger)
if fs.IsNotExist(err) {
cfg, err = DefaultConfig(path, myID, evLogger, skipPortProbing)
if err != nil {
return nil, fmt.Errorf("failed to generate default config: %w", err)
}
err = cfg.Save()
if err != nil {
return nil, fmt.Errorf("failed to save default config: %w", err)
}
slog.Info("Default config saved; edit to taste (with Syncthing stopped) or use the GUI", slogutil.FilePath(cfg.ConfigPath()))
} else if errors.Is(err, io.EOF) {
return nil, errors.New("failed to load config: unexpected end of file. Truncated or empty configuration?")
} else if err != nil {
return nil, fmt.Errorf("failed to load config: %w", err)
}
if originalVersion != config.CurrentVersion {
if originalVersion > config.CurrentVersion && !allowNewerConfig {
return nil, fmt.Errorf("config file version (%d) is newer than supported version (%d); if this is expected, use --allow-newer-config to override", originalVersion, config.CurrentVersion)
}
err = archiveAndSaveConfig(cfg, originalVersion)
if err != nil {
return nil, fmt.Errorf("config archive: %w", err)
}
}
return cfg, nil
}
func archiveAndSaveConfig(cfg config.Wrapper, originalVersion int) error {View on GitHub (pinned to 058bcd7334)
Solutions
- Restore config.xml from the .stbackup archive copies or your backup, then restart
- If no backup exists and the file is truly empty/unwanted, delete config.xml so DefaultConfig regeneration kicks in (Syncthing will create and save a default config)
- Check the same directory for numbered/backup config versions (config.xml.v0/v1... or *.stbackup) and rename one to config.xml
- Investigate why the file was truncated (disk full, crash) to prevent recurrence
Example fix
# before: config.xml is 0 bytes, startup fails $ ls -l config.xml # -rw-r--r-- 0 bytes # after: remove so a default is generated (or restore a backup) mv config.xml config.xml.broken cp config.xml.v14 config.xml # or just start syncthing to regenerate default
Defensive patterns
Strategy: validation
Validate before calling
// Before startup, check the config is non-trivial
fi, err := os.Stat(cfgPath)
if err == nil && fi.Size() == 0 {
return fmt.Errorf("config %s is empty; restore from backup or remove to regenerate", cfgPath)
} Try / catch
// Go: distinguish EOF-truncation from other load errors
if err := syncthing.LoadConfig(path, id, logger, false, false); err != nil {
if strings.Contains(err.Error(), "unexpected end of file") {
// restore last backup before retrying once
}
} Prevention
- Back up the config directory regularly — Syncthing keeps archived copies; know where they are
- Avoid external tools that rewrite config.xml non-atomically
- Monitor free disk space; truncation is often a disk-full casualty
When it happens
Trigger: Loading a config path where the file exists but is empty (0 bytes), or was truncated by a crash/power loss during Save. Triggered via lib/syncthing/utils.go LoadConfig at startup when config.Load's xml decode hits EOF before any element.
Common situations: Power loss or SIGKILL during a config write (Syncthing writes atomically, but external tools may not), an editor that emptied the file, a failed 'syncthing generate' run, or a disk-full event leaving a zero-length config.xml.
Related errors
- folder path not a directory
- folder path missing
- failed to generate config and keys: %w
- save config: %w
- current %sB < required %v
AI-assisted analysis of syncthing/syncthing@058bcd7334 (2026-08-15).
Data as JSON: /api/errors/487eafaa2d71ec57.
Report an issue: GitHub.