caddyserver/caddy · error
precompressor does not specify a Suffix value
Error message
precompressor does not specify a Suffix value
What it means
Returned in FileServer.Provision when a precompressor module's Suffix() returns an empty string. The suffix (e.g. ".gz", ".br") is appended to the original filename to locate the precompressed sidecar file; an empty suffix would make the server stat the original file itself, so provisioning fails.
Source
Thrown at modules/caddyhttp/fileserver/staticfiles.go:237
}
// 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
}
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)
}View on GitHub (pinned to 50e54ee279)
Solutions
- Return a non-empty suffix including the dot, e.g. ".gz" or ".foo".
- If suffix comes from plugin config, set the field or validate it non-empty in the plugin's Validate().
- Rebuild the plugin after the fix with xcaddy.
Example fix
// before
func (Foo) Suffix() string { return "" }
// after
func (Foo) Suffix() string { return ".foo" } Defensive patterns
Strategy: validation
Validate before calling
// In your plugin's Validate(): require a dot-prefixed, non-empty suffix
func (m *MyPrecompressor) Validate() error {
s := m.Suffix()
if s == "" || !strings.HasPrefix(s, ".") {
return fmt.Errorf("suffix must be non-empty and start with '.'")
}
return nil
} Prevention
- Document that Suffix() must include the leading dot (e.g. '.gz').
- Unit-test the module contract (AcceptEncoding/Suffix) as part of the plugin build.
- Validate plugin config early so failures surface as config errors, not runtime surprises.
When it happens
Trigger: A custom precompressor plugin whose Suffix() method returns "" — unimplemented stub, or a user-configured suffix field left blank.
Common situations: Plugin scaffolding with zero-value returns; forgetting that Suffix must include the leading dot; config-driven suffix fields left unset.
Related errors
- precompressor does not specify an Accept-Encoding value
- module %s is not precompressor
- %s: invalid configuration: %v
- getting module named '%s': %v
- unknown try policy %s
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/a858ad9cb5346eaa.
Report an issue: GitHub.