caddyserver/caddy · error

module %s is not precompressor

Error message

module %s is not precompressor

What it means

Returned in FileServer.Provision when a module loaded under the precompressed namespace does not implement the encode.Precompressed interface. The precompressed slot has a module type contract (AcceptEncoding/Suffix methods); a module that registers itself under that namespace but lacks the interface trips this check.

Source

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

	// for hide paths that are static (i.e. no placeholders), we can transform them into
	// absolute paths before the server starts for very slight performance improvement
	for i, h := range fsrv.Hide {
		if !strings.Contains(h, "{") && strings.Contains(h, separator) {
			if abs, err := caddy.FastAbs(h); err == nil {
				fsrv.Hide[i] = abs
			}
		}
	}

	// support precompressed sidecar files
	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
	}

View on GitHub (pinned to 50e54ee279)

Solutions

  1. Check the failing module name in the error and ensure it implements AcceptEncoding() string and Suffix() string (the full encode.Precompressed interface).
  2. Fix the module's CaddyModule() ID to the correct namespace and rebuild with xcaddy.
  3. Rebuild the plugin against the same Caddy version as the server binary to avoid interface drift.
  4. Remove the incompatible module from the build or from the precompressed config.

Example fix

// before: module registered without implementing the full interface
func (Foo) CaddyModule() caddy.ModuleInfo { return caddy.ModuleInfo{ID: "http.precompressed.foo", New: func() caddy.Module { return new(Foo) }} }
// after
var _ encode.Precompressed = (*Foo)(nil) // compile-time guard
func (Foo) AcceptEncoding() string { return "foo" }
func (Foo) Suffix() string { return ".foo" }
Defensive patterns

Strategy: type-guard

Type guard

// Compile-time guard in your plugin: fails the build if the interface drifts
var _ encode.Precompressed = (*MyPrecompressor)(nil)

Prevention

When it happens

Trigger: Loading a third-party or custom module whose CaddyModule ID is in the http.precompressed namespace but which does not implement encode.Precompressed (e.g. wrong method set, or registered under the wrong ID by mistake).

Common situations: Writing a custom precompressor plugin and registering it with an incorrect module ID; a plugin built against an older Caddy API where the Precompressed interface differed; type mismatch after an API refactor between Caddy versions.

Related errors


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