{"record":{"id":"70f3af3fe9b7eda9","repo":"semaphoreui/semaphore","slug":"got-non-existent-config-attribute-v","errorCode":null,"errorMessage":"got non-existent config attribute '%v'","messagePattern":"got non-existent config attribute '(.+?)'","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"util/config.go","lineNumber":1383,"sourceCode":"\t\t\t\tpanic(fmt.Errorf(\"cannot assign value of type %s to field of type %s\", convertedValue.Type(), attribute.Type()))\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\tpanic(fmt.Errorf(\"got non-existent config attribute\"))\n\t}\n}\n\nfunc getConfigValue(path string) string {\n\tattribute := reflect.ValueOf(Config)\n\tnested_path := strings.Split(path, \".\")\n\n\tfor i, nested := range nested_path {\n\t\tattribute = reflect.Indirect(attribute).FieldByName(nested)\n\t\tlastDepth := len(nested_path) == i+1\n\t\tif !lastDepth && attribute.Kind() != reflect.Struct && attribute.Kind() != reflect.Pointer ||\n\t\t\tlastDepth && attribute.Kind() == reflect.Invalid {\n\t\t\tpanic(fmt.Errorf(\"got non-existent config attribute '%v'\", path))\n\t\t}\n\t}\n\n\treturn fmt.Sprintf(\"%v\", attribute)\n}\n\nfunc validate(value any) error {\n\tt := reflect.TypeOf(value)\n\tv := reflect.ValueOf(value)\n\n\tif t.Kind() == reflect.Ptr {\n\t\tt = t.Elem()\n\t\tv = reflect.Indirect(v)\n\t}\n\n\tfor i := 0; i < t.NumField(); i++ {\n\t\tfieldType := t.Field(i)\n\t\tfieldValue := v.Field(i)","sourceCodeStart":1365,"sourceCodeEnd":1401,"githubUrl":"https://github.com/semaphoreui/semaphore/blob/1774ccb71a0a8b82eb74ea24c23ac9ab713de2fa/util/config.go#L1365-L1401","documentation":"getConfigValue panics when a dotted attribute path cannot be walked on the util.Config struct: an intermediate segment is not a struct/pointer, or the final segment does not exist (Invalid kind). It is the read-side counterpart of error 202 and indicates the path string does not match the config struct layout.","triggerScenarios":"Calling getConfigValue/GetConfig (or a feature that reads config by path) with a mistyped path like `auth.email_verification_requiredd`, or a path whose intermediate node is a scalar (e.g. `db.user.foo`).","commonSituations":"Typo in config key inside code/templates; fields renamed between versions; building paths programmatically from user input.","solutions":["Fix the dotted path to match the actual ConfigType field hierarchy","Verify each intermediate segment is a struct in util.ConfigType","Validate user-supplied config paths before passing them in","Pin/reference documentation for the deployed Semaphore version, since field names change"],"exampleFix":"// before\nval := util.GetConfig(\"db.conection.host\")\n// after\nval := util.GetConfig(\"db.connection.host\")","handlingStrategy":"validation","validationCode":"func configPathExists(path string) bool {\n    v := reflect.Indirect(reflect.ValueOf(util.Config{}))\n    parts := strings.Split(path, \".\")\n    for i, seg := range parts {\n        if v.Kind() != reflect.Struct { return false }\n        v = v.FieldByName(seg)\n        if !v.IsValid() { return false }\n        if i < len(parts)-1 && v.Kind() != reflect.Struct && v.Kind() != reflect.Pointer { return false }\n    }\n    return true\n}","typeGuard":"func isReadableConfigValue(path string) (ok bool) {\n    defer func() { _ = recover() }()\n    util.GetConfig(path)\n    return true\n}","tryCatchPattern":"func safeGet(path string) (val string, err error) {\n    defer func() {\n        if r := recover(); r != nil {\n            err = fmt.Errorf(\"bad config path %q: %v\", path, r)\n        }\n    }()\n    return util.GetConfig(path), nil\n}","preventionTips":["Only pass hardcoded, reviewed dotted paths to GetConfig","Never build config paths from untrusted user input without validation","Check intermediate segments are structs (e.g. `db`, then `connection`, then the field)","Document the deployed version's config schema where paths are referenced"],"tags":["go","reflection","config","path","panic"],"backgroundTag":"missing-config-key","analyzedSha":"1774ccb71a0a8b82eb74ea24c23ac9ab713de2fa","analyzedAt":"2026-09-07T11:00:33.293Z","contentChangedAt":"2026-09-07T11:00:33.293Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}