{"record":{"id":"19ceb794593e5325","repo":"cloudflare/cloudflared","slug":"expected-string-slice-found-t-for-s","errorCode":null,"errorMessage":"expected string slice found %T for %s","messagePattern":"expected string slice found %T for (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"config/configuration.go","lineNumber":335,"sourceCode":"\t\treturn \"\", fmt.Errorf(\"expected string found %T for %s\", raw, name)\n\t}\n\treturn \"\", nil\n}\n\nfunc (c *configFileSettings) StringSlice(name string) ([]string, error) {\n\tif raw, ok := c.Settings[name]; ok {\n\t\tif slice, ok := raw.([]interface{}); ok {\n\t\t\tstrSlice := make([]string, len(slice))\n\t\t\tfor i, v := range slice {\n\t\t\t\tstr, ok := v.(string)\n\t\t\t\tif !ok {\n\t\t\t\t\treturn nil, fmt.Errorf(\"expected string, found %T for %v\", i, v)\n\t\t\t\t}\n\t\t\t\tstrSlice[i] = str\n\t\t\t}\n\t\t\treturn strSlice, nil\n\t\t}\n\t\treturn nil, fmt.Errorf(\"expected string slice found %T for %s\", raw, name)\n\t}\n\treturn nil, nil\n}\n\nfunc (c *configFileSettings) IntSlice(name string) ([]int, error) {\n\tif raw, ok := c.Settings[name]; ok {\n\t\tif slice, ok := raw.([]interface{}); ok {\n\t\t\tintSlice := make([]int, len(slice))\n\t\t\tfor i, v := range slice {\n\t\t\t\tstr, ok := v.(int)\n\t\t\t\tif !ok {\n\t\t\t\t\treturn nil, fmt.Errorf(\"expected int, found %T for %v \", v, v)\n\t\t\t\t}\n\t\t\t\tintSlice[i] = str\n\t\t\t}\n\t\t\treturn intSlice, nil\n\t\t}\n\t\tif v, ok := raw.([]int); ok {","sourceCodeStart":317,"sourceCodeEnd":353,"githubUrl":"https://github.com/cloudflare/cloudflared/blob/2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f/config/configuration.go#L317-L353","documentation":"Returned by configFileSettings.StringSlice when the setting exists but the whole value is not a []interface{} (e.g. it is a single string, map, or scalar). The message reports the value's dynamic type and the setting name.","triggerScenarios":"Calling StringSlice(name) on a scalar setting, e.g. `origins: web` (single value instead of a list) or `origins: {a: b}`.","commonSituations":"Users specifying one item without YAML list syntax; config keys renamed so a string value is read as a slice.","solutions":["Use YAML list syntax in the config file: origins:\\n  - web.","If a single value is acceptable, wrap it in a one-element list or handle a string at the call site.","Verify the key name is the one defined as a list by the consumer."],"exampleFix":"// before (config.yml)\norigins: web\n// after\norigins:\n  - web","handlingStrategy":"validation","validationCode":"// Go\nisList := func(v interface{}) bool { _, ok := v.([]interface{}); return ok }","typeGuard":"func asList(v interface{}) ([]interface{}, bool) { l, ok := v.([]interface{}); return l, ok }","tryCatchPattern":"ss, err := settings.StringSlice(\"origins\")\nif err != nil {\n    log.Printf(\"'origins' must be a YAML list: %v\", err)\n    return err\n}","preventionTips":["Use proper YAML list syntax (- item per line) for list settings","Never pass a scalar where a list is expected","Cross-check the key against the docs for its expected shape"],"tags":["configuration","type-mismatch","string-slice"],"backgroundTag":"config-type-mismatch","analyzedSha":"2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f","analyzedAt":"2026-09-06T04:14:33.757Z","contentChangedAt":"2026-09-06T04:14:33.757Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}