caddyserver/caddy · error
unknown try policy %s
Error message
unknown try policy %s
What it means
Validate-time error from MatchFile: TryPolicy is not one of the empty string, first_exist, first_exist_fallback, largest_size, smallest_size, or most_recently_modified. The file matcher rejects unknown policy strings at config validation.
Source
Thrown at modules/caddyhttp/fileserver/matcher.go:305
// if list of files to try was omitted entirely, assume URL path
// (use placeholder instead of r.URL.Path; see issue #4146)
if m.TryFiles == nil {
m.TryFiles = []string{"{http.request.uri.path}"}
}
return nil
}
// Validate ensures m has a valid configuration.
func (m MatchFile) Validate() error {
switch m.TryPolicy {
case "",
tryPolicyFirstExist,
tryPolicyFirstExistFallback,
tryPolicyLargestSize,
tryPolicySmallestSize,
tryPolicyMostRecentlyMod:
default:
return fmt.Errorf("unknown try policy %s", m.TryPolicy)
}
return nil
}
// Match returns true if r matches m. Returns true
// if a file was matched. If so, four placeholders
// will be available:
// - http.matchers.file.relative: Path to file relative to site root
// - http.matchers.file.absolute: Path to file including site root
// - http.matchers.file.type: file or directory
// - http.matchers.file.remainder: Portion remaining after splitting file path (if configured)
func (m MatchFile) Match(r *http.Request) bool {
match, err := m.selectFile(r)
if err != nil {
// nolint:staticcheck
caddyhttp.SetVar(r.Context(), caddyhttp.MatcherErrorVarKey, err)
}
return matchView on GitHub (pinned to 50e54ee279)
Solutions
- Use exactly: first_exist, first_exist_fallback, largest_size, smallest_size, or most_recently_modified
- Omit try_policy to get the default (first_exist)
- Run caddy validate against the config before deploying
Example fix
// before
{"try_policy": "first-exist"}
// after
{"try_policy": "first_exist"} Defensive patterns
Strategy: validation
Validate before calling
var validPolicies = map[string]bool{"": true, "first_exist": true, "first_exist_fallback": true, "largest_size": true, "smallest_size": true, "most_recently_modified": true}
if !validPolicies[policy] { return fmt.Errorf("unknown try policy %s", policy) } Prevention
- Use snake_case policy names exactly as documented
- Run caddy validate on all configs in CI
When it happens
Trigger: try_files policy typo in JSON ("try_policy": "first-exist") or a policy name from docs of a different version.
Common situations: Hand-written JSON using hyphens instead of underscores; policies renamed across Caddy versions; copy-paste from try_files directives expecting nginx semantics.
Related errors
- parsing listener address: %v
- must be exactly one listener address; cannot listen on: %s
- indexing config: %v
- %s: %s field must be a string or number
- duplicate ID '%s' found at %s and %s
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/d6da1bb8fb6b2fe3.
Report an issue: GitHub.