{"record":{"id":"c25d89458846efd5","repo":"caddyserver/caddy","slug":"module-s-is-not-precompressor","errorCode":null,"errorMessage":"module %s is not precompressor","messagePattern":"module (.+?) is not precompressor","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/caddyhttp/fileserver/staticfiles.go","lineNumber":229,"sourceCode":"\t// for hide paths that are static (i.e. no placeholders), we can transform them into\n\t// absolute paths before the server starts for very slight performance improvement\n\tfor i, h := range fsrv.Hide {\n\t\tif !strings.Contains(h, \"{\") && strings.Contains(h, separator) {\n\t\t\tif abs, err := caddy.FastAbs(h); err == nil {\n\t\t\t\tfsrv.Hide[i] = abs\n\t\t\t}\n\t\t}\n\t}\n\n\t// support precompressed sidecar files\n\tmods, err := ctx.LoadModule(fsrv, \"PrecompressedRaw\")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"loading encoder modules: %v\", err)\n\t}\n\tfor modName, modIface := range mods.(map[string]any) {\n\t\tp, ok := modIface.(encode.Precompressed)\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"module %s is not precompressor\", modName)\n\t\t}\n\t\tae := p.AcceptEncoding()\n\t\tif ae == \"\" {\n\t\t\treturn fmt.Errorf(\"precompressor does not specify an Accept-Encoding value\")\n\t\t}\n\t\tsuffix := p.Suffix()\n\t\tif suffix == \"\" {\n\t\t\treturn fmt.Errorf(\"precompressor does not specify a Suffix value\")\n\t\t}\n\t\tif _, ok := fsrv.precompressors[ae]; ok {\n\t\t\treturn fmt.Errorf(\"precompressor already added: %s\", ae)\n\t\t}\n\t\tif fsrv.precompressors == nil {\n\t\t\tfsrv.precompressors = make(map[string]encode.Precompressed)\n\t\t}\n\t\tfsrv.precompressors[ae] = p\n\t}\n","sourceCodeStart":211,"sourceCodeEnd":247,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/caddyhttp/fileserver/staticfiles.go#L211-L247","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Check the failing module name in the error and ensure it implements AcceptEncoding() string and Suffix() string (the full encode.Precompressed interface).","Fix the module's CaddyModule() ID to the correct namespace and rebuild with xcaddy.","Rebuild the plugin against the same Caddy version as the server binary to avoid interface drift.","Remove the incompatible module from the build or from the precompressed config."],"exampleFix":"// before: module registered without implementing the full interface\nfunc (Foo) CaddyModule() caddy.ModuleInfo { return caddy.ModuleInfo{ID: \"http.precompressed.foo\", New: func() caddy.Module { return new(Foo) }} }\n// after\nvar _ encode.Precompressed = (*Foo)(nil) // compile-time guard\nfunc (Foo) AcceptEncoding() string { return \"foo\" }\nfunc (Foo) Suffix() string { return \".foo\" }","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"// Compile-time guard in your plugin: fails the build if the interface drifts\nvar _ encode.Precompressed = (*MyPrecompressor)(nil)","tryCatchPattern":null,"preventionTips":["Always declare interface guards for Caddy module contracts in plugins.","Build plugins against the exact Caddy version used in production (xcaddy with a pinned core version).","Smoke-test custom modules with `caddy validate` on a minimal config before shipping."],"tags":["caddy","fileserver","precompressed","module-system","interface"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}