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

  1. Restore config.xml from the .stbackup archive copies or your backup, then restart
  2. 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)
  3. Check the same directory for numbered/backup config versions (config.xml.v0/v1... or *.stbackup) and rename one to config.xml
  4. 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

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


AI-assisted analysis of syncthing/syncthing@058bcd7334 (2026-08-15). Data as JSON: /api/errors/487eafaa2d71ec57. Report an issue: GitHub.