{"record":{"id":"18d024a077035520","repo":"semaphoreui/semaphore","slug":"got-non-existent-config-attribute","errorCode":null,"errorMessage":"got non-existent config attribute","messagePattern":"got non-existent config attribute","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"util/config.go","lineNumber":1370,"sourceCode":"\t\t\terr := json.Unmarshal([]byte(value), mapValue.Interface())\n\t\t\tif err != nil {\n\t\t\t\tpanic(err)\n\t\t\t}\n\t\t\tattribute.Set(mapValue.Elem())\n\t\tdefault:\n\t\t\tnewValue, _ := CastValueToKind(value, kind)\n\t\t\tconvertedValue := reflect.ValueOf(newValue)\n\t\t\tif convertedValue.Type().AssignableTo(attribute.Type()) {\n\t\t\t\tattribute.Set(convertedValue)\n\t\t\t} else if convertedValue.Type().ConvertibleTo(attribute.Type()) {\n\t\t\t\tattribute.Set(convertedValue.Convert(attribute.Type()))\n\t\t\t} else {\n\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}","sourceCodeStart":1352,"sourceCodeEnd":1388,"githubUrl":"https://github.com/semaphoreui/semaphore/blob/1774ccb71a0a8b82eb74ea24c23ac9ab713de2fa/util/config.go#L1352-L1388","documentation":"setConfigValue panics when the reflect.Value for the requested config attribute is invalid, i.e. the attribute path does not exist in the util.Config struct. Typically the caller looked up a path that matched no field (FieldByName returned zero Value) and passed it in.","triggerScenarios":"Calling a config-set API with a dotted path or attribute name that does not correspond to any field of ConfigType; typos in attribute names; referencing fields removed/renamed in a newer Semaphore version.","commonSituations":"Typo in an env-config key name; automation/scripts setting config values that no longer exist; migrations referencing old config fields.","solutions":["Correct the attribute name/path to an existing ConfigType field","Inspect util.ConfigType (or the config reference docs) for the exact field name","Use util.ConfigValidate / grep the struct to confirm the path exists before setting","Update scripts that reference renamed/removed config fields"],"exampleFix":"// before\nutil.ConfigSetAttribute(\"access_key_expir\", \"0\")\n// after\nutil.ConfigSetAttribute(\"access_key_expiration\", \"0\")","handlingStrategy":"validation","validationCode":"func configFieldExists(name string) bool {\n    _, ok := reflect.TypeOf(util.ConfigType{}).FieldByName(name)\n    return ok\n}\nif !configFieldExists(\"access_key_expiration\") { /* abort */ }","typeGuard":"func validConfigPath(path string) bool {\n    v := reflect.Indirect(reflect.ValueOf(util.Config{}))\n    for _, seg := range strings.Split(path, \".\") {\n        if v.Kind() != reflect.Struct { return false }\n        v = v.FieldByName(seg)\n        if !v.IsValid() { return false }\n    }\n    return true\n}","tryCatchPattern":"func safeGetConfig(path string) (val string, err error) {\n    defer func() {\n        if r := recover(); r != nil {\n            err = fmt.Errorf(\"unknown config attribute %q: %v\", path, r)\n        }\n    }()\n    return util.GetConfig(path), nil\n}","preventionTips":["Copy attribute names from util/config.go or the config reference, never from memory","Grep the struct for the field name before scripting config changes","After upgrades, diff your config overrides against the new ConfigType fields"],"tags":["go","reflection","config","panic","missing-field"],"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"}