cloudflare/cloudflared · error

expected duration found %T for %s

Error message

expected duration found %T for %s

What it means

Type-mismatch error in configFileSettings.Duration: a config-file setting read as a duration is neither a time.Duration nor a duration string (e.g. it is an int, bool, or map in the parsed YAML). The accessor returns zero and this error instead of guessing a conversion.

Source

Thrown at config/configuration.go:297

func (c *configFileSettings) Int(name string) (int, error) {
	if raw, ok := c.Settings[name]; ok {
		if v, ok := raw.(int); ok {
			return v, nil
		}
		return 0, fmt.Errorf("expected int found %T for %s", raw, name)
	}
	return 0, nil
}

func (c *configFileSettings) Duration(name string) (time.Duration, error) {
	if raw, ok := c.Settings[name]; ok {
		switch v := raw.(type) {
		case time.Duration:
			return v, nil
		case string:
			return time.ParseDuration(v)
		}
		return 0, fmt.Errorf("expected duration found %T for %s", raw, name)
	}
	return 0, nil
}

func (c *configFileSettings) Float64(name string) (float64, error) {
	if raw, ok := c.Settings[name]; ok {
		if v, ok := raw.(float64); ok {
			return v, nil
		}
		return 0, fmt.Errorf("expected float found %T for %s", raw, name)
	}
	return 0, nil
}

func (c *configFileSettings) String(name string) (string, error) {
	if raw, ok := c.Settings[name]; ok {
		if v, ok := raw.(string); ok {
			return v, nil

View on GitHub (pinned to 2253eeeb25)

Solutions

  1. Write the value as a duration string with a unit in the config file (grace-period: 30s).
  2. If a bare number is intentional seconds, change the call site to read Int and multiply by time.Second.
  3. Handle the ParseDuration error path separately for string values with bad formats.

Example fix

// before (config.yml)
grace-period: 30
// after
grace-period: 30s
Defensive patterns

Strategy: validation

Validate before calling

// Go
typeAssertDuration := func(v interface{}) (time.Duration, error) {
    switch t := v.(type) {
    case time.Duration: return t, nil
    case string: return time.ParseDuration(t)
    default: return 0, fmt.Errorf("not a duration: %T", v)
    }
}

Type guard

func asDuration(v interface{}) (time.Duration, bool) { d, ok := v.(time.Duration); return d, ok }

Try / catch

d, err := settings.Duration("grace-period")
if err != nil {
    log.Printf("'grace-period' must be like 30s/5m: %v", err)
    return err
}

Prevention

When it happens

Trigger: Calling Duration(name) where the stored value is an int, bool, or a string in an invalid format is handled separately (ParseDuration error); this error fires for non-duration, non-string types — e.g. `grace-period: 5` (bare number instead of "5s").

Common situations: Users writing bare numbers in YAML where a duration string like 30s/1m is required; config keys copied from examples with wrong units.

Understand the failure class

Background: "invalid duration" / "failed to parse duration": why your timeout, interval, or TTL string is rejected and which formats each library accepts — this error's family across 32 libraries.

Related errors


AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06). Data as JSON: /api/errors/eb947521f92d3250. Report an issue: GitHub.