{"record":{"id":"e000f2d573dd14bf","repo":"hyperledger/fabric","slug":"value-of-file-was-nil","errorCode":null,"errorMessage":"Value of File: was nil","messagePattern":"Value of File: was nil","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/viperutil/config_util.go","lineNumber":296,"sourceCode":"\tswitch v.Kind() {\n\tcase reflect.String:\n\t\treturn data, nil\n\tcase reflect.Map:\n\t\td := data.(map[string]any)\n\t\tfileName, ok := d[\"File\"]\n\t\tif !ok {\n\t\t\tfileName, ok = d[\"file\"]\n\t\t}\n\t\tswitch {\n\t\tcase ok && fileName != nil:\n\t\t\tbytes, err := os.ReadFile(fileName.(string))\n\t\t\tif err != nil {\n\t\t\t\treturn data, err\n\t\t\t}\n\t\t\treturn string(bytes), nil\n\t\tcase ok:\n\t\t\t// fileName was nil\n\t\t\treturn nil, fmt.Errorf(\"Value of File: was nil\")\n\t\t}\n\t}\n\treturn data, nil\n}\n\nfunc pemBlocksFromFileDecodeHook(f reflect.Kind, t reflect.Kind, data any) (any, error) {\n\t// \"to\" type should be string\n\tif t != reflect.Slice {\n\t\treturn data, nil\n\t}\n\t// \"from\" type should be map\n\tif f != reflect.Map {\n\t\treturn data, nil\n\t}\n\tv := reflect.ValueOf(data)\n\tswitch v.Kind() {\n\tcase reflect.String:\n\t\treturn data, nil","sourceCodeStart":278,"sourceCodeEnd":314,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/common/viperutil/config_util.go#L278-L314","documentation":"stringFromFileDecodeHook is a viper decode hook that reads a config value from a file when the value is given as a map like { file: /path/to/key.pem }. If the map contains a \"File\"/\"file\" key whose value is nil, the hook cannot read any file and returns this error instead of silently producing an empty string.","triggerScenarios":"A viper config (YAML/TOML or programmatically built map) supplies a value such as \"File:\" or {\"file\": nil} for a string field that supports the file-indirection syntax — the key exists but its value is nil.","commonSituations":"YAML entries like \"tls.cert: File:\" left with no value after template rendering, env-var overrides that blank out the file path, or Helm/templating substituting an empty variable into the file key.","solutions":["Set an actual file path under the File key, e.g. File: /path/to/cert.pem.","If the value should be inline, replace the map with the literal string instead of an empty File map.","Check template/Helm rendering so the path variable isn't empty at deploy time.","Verify the file key spelling and that no overriding env var sets it to nil/empty."],"exampleFix":"// before (config.yaml)\nexternalListeners:\n  - Certificate: File:\n# after\nexternalListeners:\n  - Certificate:\n      File: /etc/hyperledger/fabric/tls/server.crt","handlingStrategy":"validation","validationCode":"// Reject nil-valued File maps before viper unmarshal\nfunc checkFileIndirection(cfg map[string]any) error {\n\tvar walk func(m map[string]any) error\n\twalk = func(m map[string]any) error {\n\t\tfor k, v := range m {\n\t\t\tif (k == \"File\" || k == \"file\") && v == nil {\n\t\t\t\treturn fmt.Errorf(\"File key present but nil at %s\", k)\n\t\t\t}\n\t\t\tif sub, ok := v.(map[string]any); ok {\n\t\t\t\tif err := walk(sub); err != nil { return err }\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t}\n\treturn walk(cfg)\n}","typeGuard":"func hasFileValue(m map[string]any) (string, bool) {\n\tv, ok := m[\"File\"]\n\tif !ok { v, ok = m[\"file\"] }\n\tif !ok || v == nil { return \"\", false }\n\ts, ok := v.(string)\n\treturn s, ok && s != \"\"\n}","tryCatchPattern":"err := viper.Unmarshal(cfg, viperutil.DecodeHookFunc)\nif err != nil {\n\tif strings.Contains(err.Error(), \"Value of File: was nil\") {\n\t\treturn fmt.Errorf(\"a File: config entry has no path set; check YAML rendering: %w\", err)\n\t}\n\treturn err\n}","preventionTips":["Never leave a File: key empty in YAML; always give an absolute path.","Check Helm/template output for empty substitutions before deploy.","Verify referenced files exist (os.Stat) as part of startup validation.","Prefer inline strings for small certs only when file indirection is genuinely unneeded."],"tags":["go","viper","config","nil-value","hyperledger-fabric"],"backgroundTag":"missing-config-value","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}