hyperledger/fabric · error
Value of File: was nil
Error message
Value of File: was nil
What it means
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.
Source
Thrown at common/viperutil/config_util.go:296
switch v.Kind() {
case reflect.String:
return data, nil
case reflect.Map:
d := data.(map[string]any)
fileName, ok := d["File"]
if !ok {
fileName, ok = d["file"]
}
switch {
case ok && fileName != nil:
bytes, err := os.ReadFile(fileName.(string))
if err != nil {
return data, err
}
return string(bytes), nil
case ok:
// fileName was nil
return nil, fmt.Errorf("Value of File: was nil")
}
}
return data, nil
}
func pemBlocksFromFileDecodeHook(f reflect.Kind, t reflect.Kind, data any) (any, error) {
// "to" type should be string
if t != reflect.Slice {
return data, nil
}
// "from" type should be map
if f != reflect.Map {
return data, nil
}
v := reflect.ValueOf(data)
switch v.Kind() {
case reflect.String:
return data, nilView on GitHub (pinned to 2736b63f8f)
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.
Example fix
// before (config.yaml)
externalListeners:
- Certificate: File:
# after
externalListeners:
- Certificate:
File: /etc/hyperledger/fabric/tls/server.crt Defensive patterns
Strategy: validation
Validate before calling
// Reject nil-valued File maps before viper unmarshal
func checkFileIndirection(cfg map[string]any) error {
var walk func(m map[string]any) error
walk = func(m map[string]any) error {
for k, v := range m {
if (k == "File" || k == "file") && v == nil {
return fmt.Errorf("File key present but nil at %s", k)
}
if sub, ok := v.(map[string]any); ok {
if err := walk(sub); err != nil { return err }
}
}
return nil
}
return walk(cfg)
} Type guard
func hasFileValue(m map[string]any) (string, bool) {
v, ok := m["File"]
if !ok { v, ok = m["file"] }
if !ok || v == nil { return "", false }
s, ok := v.(string)
return s, ok && s != ""
} Try / catch
err := viper.Unmarshal(cfg, viperutil.DecodeHookFunc)
if err != nil {
if strings.Contains(err.Error(), "Value of File: was nil") {
return fmt.Errorf("a File: config entry has no path set; check YAML rendering: %w", err)
}
return err
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "missing required config value" errors: why libraries refuse to start when a configuration key is empty, unset, or blank — this error's family across 48 libraries.
Related errors
- value '%s' overflows uint32
- organization %s not found
- config ID illegal, cannot be empty
- config ID illegal, cannot be longer than %d
- name '%s' for config ID is not allowed
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/e000f2d573dd14bf.
Report an issue: GitHub.