bcicen/ctop · error

failed to write config

Error message

failed to write config: %s

What it means

After the config file opens successfully, Write encodes exportConfig() as TOML via toml.NewEncoder(file).Encode. If encoding/writing to the file fails, the error is wrapped as 'failed to write config'.

Solutions

  1. Check free disk space on the filesystem holding the config
  2. Audit the exported config struct for TOML-unsupported types (channels, funcs, complex numbers, non-string map keys)
  3. Re-run write after removing any special file at the config path

Example fix

// before
type Config struct { Callbacks map[int]func() } // unsupported by TOML
// after
type Config struct { Callbacks map[string]string }
Defensive patterns

Strategy: try-catch

Validate before calling

// keep config struct TOML-encodable: no funcs/channels/non-string map keys
toml.Marshal(exportConfig()) // dry-run encode to memory first

Try / catch

_, err := config.Write()
if err != nil && strings.HasPrefix(err.Error(), "failed to write config") {
    // free disk space / fix unsupported field types
}

Prevention

When it happens

Trigger: toml Encoder.Encode returns an error — typically an I/O write failure (disk full, closed handle) or a value in the config struct that the TOML encoder cannot serialize (e.g. unsupported type like a map with non-string keys, channel, func).

Common situations: Disk full on the volume holding $HOME; config struct gained a field of an unsupported type after an upgrade; file replaced by a pipe/fifo or special file mid-write.

Related errors


AI-assisted analysis of bcicen/ctop@59f00dd6aa (2026-09-02). Data as JSON: /api/errors/12a45ef65c43afe8. Report an issue: GitHub.

Appendix: source

Thrown at config/file.go:109

		}
	}

	// remove prior to writing new file
	if err := os.Remove(path); err != nil {
		if !os.IsNotExist(err) {
			return path, err
		}
	}

	file, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0644)
	if err != nil {
		return path, fmt.Errorf("failed to open config for writing: %s", err)
	}

	writer := toml.NewEncoder(file)
	err = writer.Encode(exportConfig())
	if err != nil {
		return path, fmt.Errorf("failed to write config: %s", err)
	}

	return path, nil
}

// determine config path from environment
func getConfigPath() (path string, err error) {
	homeDir, ok := os.LookupEnv("HOME")
	if !ok {
		return path, fmt.Errorf("$HOME not set")
	}

	// use xdg config home if possible
	if xdgSupport() {
		xdgHome, ok := os.LookupEnv("XDG_CONFIG_HOME")
		if !ok {
			xdgHome = fmt.Sprintf("%s/.config", homeDir)
		}

View on GitHub (pinned to 59f00dd6aa)