caddyserver/caddy · error

unmarshaling admin listener address from config: %v

Error message

unmarshaling admin listener address from config: %v

What it means

DetermineAdminAPIAddress unmarshals only the top-level {"admin": {...}} field of the loaded config to find admin.listen; if those bytes are not valid JSON this wrap of the json.Unmarshal error is returned. With a --adapter this should not happen (the adapter output is JSON), so it nearly always means a raw JSON file is corrupt.

Source

Thrown at cmd/commandfuncs.go:894

		if len(loadedConfig) == 0 {
			// get the config in caddy's native format
			loadedConfig, loadedConfigFile, _, err = LoadConfig(configFile, configAdapter)
			if err != nil {
				return "", err
			}
			if loadedConfigFile == "" {
				return "", fmt.Errorf("no config file to load; either use --config flag or ensure Caddyfile exists in current directory")
			}
		}

		// get the address of the admin listener from the config
		if len(loadedConfig) > 0 {
			var tmpStruct struct {
				Admin caddy.AdminConfig `json:"admin"`
			}
			err := json.Unmarshal(loadedConfig, &tmpStruct)
			if err != nil {
				return "", fmt.Errorf("unmarshaling admin listener address from config: %v", err)
			}
			if tmpStruct.Admin.Listen != "" {
				return tmpStruct.Admin.Listen, nil
			}
		}
	}

	// Fallback to the default listen address otherwise
	return caddy.DefaultAdminListen, nil
}

// configFileWithRespectToDefault returns the filename to use for loading the config, based
// on whether a config file is already specified and a supported default config file exists.
func configFileWithRespectToDefault(logger *zap.Logger, configFile string) (string, error) {
	const defaultCaddyfile = "Caddyfile"

	// if no input file was specified, try a default Caddyfile if the Caddyfile adapter is plugged in
	if configFile == "" && caddyconfig.GetAdapter("caddyfile") != nil {

View on GitHub (pinned to 50e54ee279)

Solutions

  1. Validate the JSON: jq . /path/to/config.json or caddy validate --config <file>
  2. Write config files atomically (write temp file, then rename) so readers never see partial content
  3. If using a Caddyfile or other format, pass the matching --adapter so it is converted to JSON first

Example fix

# before
caddy reload --config caddy.json   # file has trailing comma

# after
jq . caddy.json >/dev/null && caddy reload --config caddy.json
Defensive patterns

Strategy: validation

Validate before calling

// Pre-parse to catch corrupt JSON before the CLI does:
var probe struct{ Admin caddy.AdminConfig `json:"admin"` }
if err := json.Unmarshal(raw, &probe); err != nil { return fmt.Errorf("config JSON invalid: %w", err) }

Prevention

When it happens

Trigger: Passing --config pointing at a hand-edited JSON file with a typo; a truncated file (disk full, interrupted write); a JSON file with a BOM or CRLF issues that break parsing at the admin key level.

Common situations: Scripts that generate the JSON config emitting invalid JSON; editing the config in place while a reload tool concurrently reads it.

Related errors


AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15). Data as JSON: /api/errors/3410c68cade66443. Report an issue: GitHub.