cloudflare/cloudflared · error

expected string, found %T for %v

Error message

expected string, found %T for %v

What it means

Returned by configFileSettings.StringSlice while converting a []interface{} element to string: an element inside the slice is not a string. Note the message formats `i` (the index) as %T and the value `v` as %v, so the message actually prints 'int' (the type of the index) rather than the element's type — a known formatting bug in the error text.

Source

Thrown at config/configuration.go:329

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

func (c *configFileSettings) StringSlice(name string) ([]string, error) {
	if raw, ok := c.Settings[name]; ok {
		if slice, ok := raw.([]interface{}); ok {
			strSlice := make([]string, len(slice))
			for i, v := range slice {
				str, ok := v.(string)
				if !ok {
					return nil, fmt.Errorf("expected string, found %T for %v", i, v)
				}
				strSlice[i] = str
			}
			return strSlice, nil
		}
		return nil, fmt.Errorf("expected string slice found %T for %s", raw, name)
	}
	return nil, nil
}

func (c *configFileSettings) IntSlice(name string) ([]int, error) {
	if raw, ok := c.Settings[name]; ok {
		if slice, ok := raw.([]interface{}); ok {
			intSlice := make([]int, len(slice))
			for i, v := range slice {
				str, ok := v.(int)
				if !ok {
					return nil, fmt.Errorf("expected int, found %T for %v ", v, v)

View on GitHub (pinned to 2253eeeb25)

Solutions

  1. Make every element of the list a string in the config file (quote numeric entries).
  2. Note the message shows the index position, not the element type — check that element of the list.
  3. Handle the error at the call site by falling back to per-element conversion if mixed types are expected.

Example fix

// before (config.yml)
origins:
  - 8080
  - web
// after
origins:
  - "8080"
  - web
Defensive patterns

Strategy: type-guard

Validate before calling

// Go: validate all elements are strings before calling
allStrings := func(raw []interface{}) bool {
    for _, v := range raw { if _, ok := v.(string); !ok { return false } }
    return true
}

Type guard

func asStringSlice(v interface{}) ([]string, bool) {
    list, ok := v.([]interface{}); if !ok { return nil, false }
    out := make([]string, len(list))
    for i, e := range list { s, ok := e.(string); if !ok { return nil, false }; out[i] = s }
    return out, true
}

Try / catch

ss, err := settings.StringSlice("origins")
if err != nil {
    log.Printf("'origins' must be a list of strings: %v", err)
    return err
}

Prevention

When it happens

Trigger: Calling StringSlice(name) on a list where at least one element is not a string, e.g. `origins: [8080, "web"]` in YAML.

Common situations: Mixed-type YAML lists; numeric ports or booleans inside string lists; hand-edited config files.

Related errors


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