caddyserver/caddy · error

precompressor already added: %s

Error message

precompressor already added: %s

What it means

Returned in FileServer.Provision when two configured precompressor modules report the same Accept-Encoding value. The precompressors map is keyed by Accept-Encoding, so a duplicate would silently overwrite one module's sidecar suffix with another's; Caddy rejects the config instead.

Source

Thrown at modules/caddyhttp/fileserver/staticfiles.go:240

	mods, err := ctx.LoadModule(fsrv, "PrecompressedRaw")
	if err != nil {
		return fmt.Errorf("loading encoder modules: %v", err)
	}
	for modName, modIface := range mods.(map[string]any) {
		p, ok := modIface.(encode.Precompressed)
		if !ok {
			return fmt.Errorf("module %s is not precompressor", modName)
		}
		ae := p.AcceptEncoding()
		if ae == "" {
			return fmt.Errorf("precompressor does not specify an Accept-Encoding value")
		}
		suffix := p.Suffix()
		if suffix == "" {
			return fmt.Errorf("precompressor does not specify a Suffix value")
		}
		if _, ok := fsrv.precompressors[ae]; ok {
			return fmt.Errorf("precompressor already added: %s", ae)
		}
		if fsrv.precompressors == nil {
			fsrv.precompressors = make(map[string]encode.Precompressed)
		}
		fsrv.precompressors[ae] = p
	}

	if fsrv.Browse != nil {
		// check sort options
		for idx, sortOption := range fsrv.Browse.SortOptions {
			switch idx {
			case 0:
				if sortOption != sortByName && sortOption != sortByNameDirFirst && sortOption != sortBySize && sortOption != sortByTime {
					return fmt.Errorf("the first option must be one of the following: %s, %s, %s, %s, but got %s", sortByName, sortByNameDirFirst, sortBySize, sortByTime, sortOption)
				}
			case 1:
				if sortOption != sortOrderAsc && sortOption != sortOrderDesc {
					return fmt.Errorf("the second option must be one of the following: %s, %s, but got %s", sortOrderAsc, sortOrderDesc, sortOption)

View on GitHub (pinned to 50e54ee279)

Solutions

  1. Deduplicate the precompressed list so each Accept-Encoding appears once.
  2. If two plugins claim the same encoding, keep only one in the build (xcaddy build flags) or in the config.
  3. Run `caddy validate` after editing the precompressed config to catch this before restart.

Example fix

# before
precompressed zstd gzip gzip br
# after
precompressed zstd gzip br
Defensive patterns

Strategy: validation

Validate before calling

# Lint your Caddyfile before deploy: no duplicate tokens in precompressed
line=$(grep -E '^\s*precompressed' Caddyfile | sed 's/^\s*precompressed//')
seen=""; for tok in $line; do
  case " $seen " in *" $tok "*) echo "duplicate precompressor: $tok"; exit 1;; esac
  seen="$seen $tok"
done

Prevention

When it happens

Trigger: Listing the same encoding twice (e.g. `precompressed gzip gzip` in Caddyfile, or two keys mapping to modules with AcceptEncoding() == "gzip" in JSON), or two different plugins that both claim the same encoding token.

Common situations: Copy-paste duplication in the precompressed list; installing two third-party plugins that both implement gzip/zstd; JSON config hand-edited to add an encoding already provided by a built-in module.

Related errors


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