glanceapp/glance · error
readFileFromEnv: reading file from %s: %v
Error message
readFileFromEnv: reading file from %s: %v
What it means
Thrown by parseConfigVariableOfType for {{ file-from-env.NAME }} at the final stage: the env var exists, its value is absolute, but os.ReadFile of that path fails. The error interpolates the env variable NAME (not the path) plus the underlying fs error, so check the env var's value to find the actual path that failed.
Source
Thrown at internal/glance/config.go:227
return strings.TrimSpace(string(secret)), false, nil
case configVarTypeFileFromEnv:
if !envVariableNamePattern.MatchString(variableName) {
return "", true, nil
}
filePath, found := os.LookupEnv(variableName)
if !found {
return "", false, fmt.Errorf("readFileFromEnv: environment variable %s not found", variableName)
}
if !filepath.IsAbs(filePath) {
return "", false, fmt.Errorf("readFileFromEnv: file path %s is not absolute", filePath)
}
fileContents, err := os.ReadFile(filePath)
if err != nil {
return "", false, fmt.Errorf("readFileFromEnv: reading file from %s: %v", variableName, err)
}
return strings.TrimSpace(string(fileContents)), false, nil
default:
return "", true, nil
}
}
func formatWidgetInitError(err error, w widget) error {
return fmt.Errorf("%s widget: %v", w.GetType(), err)
}
var configIncludePattern = regexp.MustCompile(`(?m)^([ \t]*)(?:-[ \t]*)?(?:!|\$)include:[ \t]*(.+)$`)
func parseYAMLIncludes(mainFilePath string) ([]byte, map[string]struct{}, error) {
return recursiveParseYAMLIncludes(mainFilePath, nil, 0)
}
View on GitHub (pinned to 91324e8de7)
Solutions
- Verify the path stored in the env var exists and is a regular file: `echo $API_KEY_FILE; ls -l $(eval echo $API_KEY_FILE)`.
- Fix permissions: chmod 644 (or chown to the Glance user) so the process can read it.
- In containers, confirm the volume/secret mount lands at the exact absolute path the env var names.
- Read the wrapped fs error — 'no such file or directory' vs 'permission denied' tells you which fix applies.
Example fix
# before: path typo $ export API_KEY_FILE=/etc/glance/api_keys # directory # after $ export API_KEY_FILE=/etc/glance/api_key # regular readable file
Defensive patterns
Strategy: validation
Validate before calling
for var in $(grep -oE '\{\{ *file-from-env\.[A-Za-z_][A-Za-z0-9_]* *\}\}' glance.yml | sed -E 's/.*file-from-env\.([A-Za-z0-9_]+).*/\1/'); do
p=$(printenv "$var") || exit 1
[ -f "$p" ] && [ -r "$p" ] || { echo "cannot read $var -> $p"; exit 1; }
done Prevention
- Pre-flight check that every *_FILE target exists and is readable by the service user.
- Mount volumes/secrets before Glance starts in containers.
- Check wrapped fs error text to distinguish missing file from permission denied.
When it happens
Trigger: API_KEY_FILE=/etc/glance/api_key where the file does not exist, the directory is missing, the Glance process user lacks read permission, or the path points to a directory instead of a file.
Common situations: File not yet created at deploy time; file owned by root with 0600 while Glance runs as non-root; volume not mounted into the container at the expected path; typo in the absolute path inside the env var.
Related errors
- reading secret file: %v
- readFileFromEnv: environment variable %s not found
- parsing variable: %v
- environment variable %s not found
- invalid first day of week
AI-assisted analysis of glanceapp/glance@91324e8de7 (2026-08-15).
Data as JSON: /api/errors/664f788d3bcba170.
Report an issue: GitHub.