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 match

View on GitHub (pinned to 50e54ee279)

Solutions

  1. Use exactly: first_exist, first_exist_fallback, largest_size, smallest_size, or most_recently_modified
  2. Omit try_policy to get the default (first_exist)
  3. 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

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


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