caddyserver/caddy · error

%v; additionally, restoring old config: %v

Error message

%v; additionally, restoring old config: %v

What it means

While indexing the new config's @id fields (indexConfigObjects), a failure occurred, and the recovery path tried to restore the previous config by unmarshaling the stored rawCfgJSON — which also failed. This compound error reports both the original indexing error and the restore failure; the in-memory raw config may now be inconsistent with the running config until the next successful load.

Source

Thrown at caddy.go:233

			Err:        fmt.Errorf("encoding new config: %v", err),
		}
	}

	// if nothing changed, no need to do a whole reload unless the client forces it
	if !forceReload && bytes.Equal(rawCfgJSON, newCfg) {
		Log().Info("config is unchanged")
		return errSameConfig
	}

	// find any IDs in this config and index them
	idx := make(map[string]string)
	err = indexConfigObjects(rawCfg[rawConfigKey], "/"+rawConfigKey, idx)
	if err != nil {
		if len(rawCfgJSON) > 0 {
			var oldCfg any
			err2 := json.Unmarshal(rawCfgJSON, &oldCfg)
			if err2 != nil {
				err = fmt.Errorf("%v; additionally, restoring old config: %v", err, err2)
			}
			rawCfg[rawConfigKey] = oldCfg
		} else {
			rawCfg[rawConfigKey] = nil
		}
		return APIError{
			HTTPStatus: http.StatusBadRequest,
			Err:        fmt.Errorf("indexing config: %v", err),
		}
	}

	// load this new config; if it fails, we need to revert to
	// our old representation of caddy's actual config
	err = unsyncedDecodeAndRun(newCfg, true)
	if err != nil {
		if len(rawCfgJSON) > 0 {
			// restore old config state to keep it consistent
			// with what caddy is still running; we need to

View on GitHub (pinned to 50e54ee279)

Solutions

  1. Read both messages: the first is the indexing failure (duplicate/invalid @id), the second the restore failure.
  2. Fix the @id problem in the submitted config (uniqueness, string/number values).
  3. Restart Caddy from a known-good config file to rebuild consistent in-memory state — the process may hold a mutated rawCfg.
  4. Audit any custom code that touches rawCfg/rawCfgJSON, as stock Caddy cannot produce the second failure.
Defensive patterns

Strategy: try-catch

Try / catch

if err := postLoad(cfg); err != nil && strings.Contains(err.Error(), "additionally, restoring old config") {
    // both the change AND rollback failed: state is suspect
    log.Fatal("config index + rollback failed; restart Caddy from file")
}

Prevention

When it happens

Trigger: A config change whose @id handling fails (duplicate IDs, wrong @id type) while the previously stored encoded config has become unmarshalable — essentially only possible when rawCfgJSON was corrupted by faulty custom code, since it was produced by json.Marshal. Returned as the inner error of the 'indexing config' APIError.

Common situations: Forked Caddy or plugins manipulating rawCfgJSON/rawCfg directly; memory corruption-class bugs; practically unreachable in stock Caddy. Seeing it means both the change and the rollback path are broken.

Related errors


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