{"record":{"id":"29d4235f070c39da","repo":"flipped-aurora/gin-vue-admin","slug":"fatal-error-unmarshal-config-w","errorCode":null,"errorMessage":"fatal error unmarshal config: %w","messagePattern":"fatal error unmarshal config: %w","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"server/core/viper.go","lineNumber":36,"sourceCode":"\tconfig := getConfigPath()\n\n\tv := viper.New()\n\tv.SetConfigFile(config)\n\tv.SetConfigType(\"yaml\")\n\terr := v.ReadInConfig()\n\tif err != nil {\n\t\tpanic(fmt.Errorf(\"fatal error config file: %w\", err))\n\t}\n\tv.WatchConfig()\n\n\tv.OnConfigChange(func(e fsnotify.Event) {\n\t\tfmt.Println(\"config file changed:\", e.Name)\n\t\tif err = v.Unmarshal(&global.GVA_CONFIG); err != nil {\n\t\t\tfmt.Println(err)\n\t\t}\n\t})\n\tif err = v.Unmarshal(&global.GVA_CONFIG); err != nil {\n\t\tpanic(fmt.Errorf(\"fatal error unmarshal config: %w\", err))\n\t}\n\n\t// root 适配性 根据root位置去找到对应迁移位置,保证root路径有效\n\tglobal.GVA_CONFIG.AutoCode.Root, _ = filepath.Abs(\"..\")\n\treturn v\n}\n\n// getConfigPath 获取配置文件路径, 优先级: 命令行 > 环境变量 > 默认值\nfunc getConfigPath() (config string) {\n\t// `-c` flag parse\n\tflag.StringVar(&config, \"c\", \"\", \"choose config file.\")\n\tflag.Parse()\n\tif config != \"\" { // 命令行参数不为空 将值赋值于config\n\t\tfmt.Printf(\"您正在使用命令行的 '-c' 参数传递的值, config 的路径为 %s\\n\", config)\n\t\treturn\n\t}\n\tif env := os.Getenv(internal.ConfigEnv); env != \"\" { // 判断环境变量 GVA_CONFIG\n\t\tconfig = env","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/flipped-aurora/gin-vue-admin/blob/3136500ef380842b0eb6c4daa87c3f8a47fcf9e0/server/core/viper.go#L18-L54","documentation":"After viper successfully reads the config file, Viper() unmarshals it into global.GVA_CONFIG. If the mapping fails (struct field type mismatch with YAML value types), it panics with this error since a partially-loaded config is unsafe.","triggerScenarios":"Config file parses as YAML but a value cannot be decoded into the corresponding field of config.Server/GlobalConfig, e.g. a string where an int is expected, or wrong nesting level of a map key.","commonSituations":"Upgrading gva to a version with a changed config struct while keeping an old config.yaml; hand-editing and mistyping a value type (port as \"8080\" with quotes may still decode, but nested maps misplaced won't); adding keys at the wrong indent level.","solutions":["Compare your config.yaml against the latest config.yaml example shipped with the server version and fix mismatched types/structure","Check the wrapped unmarshal error for the exact field path and expected type","Add any newly introduced config sections required by the upgraded version","Re-merge custom settings into a fresh example config rather than patching the old one"],"exampleFix":"// before\nsystem:\n  port: \"8888\"\n  addr-mismatch: true   # unknown/misspelled key or wrong type\n// after\nsystem:\n  port: 8888\n  addr: 8888            # match current struct field names/types","handlingStrategy":"validation","validationCode":"var probe map[string]interface{}\nif err := yaml.Unmarshal(content, &probe); err != nil {\n    log.Fatalf(\"YAML syntax invalid: %v\", err)\n}\n// then diff keys/types against the current example config","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Diff your config against the version-matched example after every upgrade","Keep numeric fields unquoted and nested maps at correct indent levels","Test config loading in CI with the real struct before deploying"],"tags":["viper","config","unmarshal","panic","startup"],"backgroundTag":"config-unmarshal-type-mismatch","analyzedSha":"3136500ef380842b0eb6c4daa87c3f8a47fcf9e0","analyzedAt":"2026-08-31T13:50:02.721Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}