{"record":{"id":"2d3876b4af7c8e9b","repo":"glanceapp/glance","slug":"environment-variable-s-not-found","errorCode":null,"errorMessage":"environment variable %s not found","messagePattern":"environment variable (.+?) not found","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/glance/config.go","lineNumber":199,"sourceCode":"\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn replaced, nil\n}\n\n// When the bool return value is true, it indicates that the caller should use the original value\nfunc parseConfigVariableOfType(variableType, variableName string) (string, bool, error) {\n\tswitch variableType {\n\tcase configVarTypeEnv:\n\t\tif !envVariableNamePattern.MatchString(variableName) {\n\t\t\treturn \"\", true, nil\n\t\t}\n\n\t\tv, found := os.LookupEnv(variableName)\n\t\tif !found {\n\t\t\treturn \"\", false, fmt.Errorf(\"environment variable %s not found\", variableName)\n\t\t}\n\n\t\treturn v, false, nil\n\tcase configVarTypeSecret:\n\t\tsecretPath := filepath.Join(\"/run/secrets\", variableName)\n\t\tsecret, err := os.ReadFile(secretPath)\n\t\tif err != nil {\n\t\t\treturn \"\", false, fmt.Errorf(\"reading secret file: %v\", err)\n\t\t}\n\n\t\treturn strings.TrimSpace(string(secret)), false, nil\n\tcase configVarTypeFileFromEnv:\n\t\tif !envVariableNamePattern.MatchString(variableName) {\n\t\t\treturn \"\", true, nil\n\t\t}\n\n\t\tfilePath, found := os.LookupEnv(variableName)\n\t\tif !found {","sourceCodeStart":181,"sourceCodeEnd":217,"githubUrl":"https://github.com/glanceapp/glance/blob/91324e8de762702e97b0ac5c8e36271d644d8642/internal/glance/config.go#L181-L217","documentation":"Thrown by parseConfigVariableOfType for {{ env.NAME }} expressions when os.LookupEnv reports the variable is not set at all. Deliberately distinguishes 'unset' from 'set to empty string' — an empty-but-set variable is accepted. Only fires when the variable name matches envVariableNamePattern (otherwise the original text is kept unchanged).","triggerScenarios":"glance.yml contains {{ env.MY_VAR }} and MY_VAR is not present in the process environment when Glance starts (systemd unit, Docker container, or shell where it was never exported).","commonSituations":"Starting Glance via systemd/docker-compose without passing the env vars referenced in config; CI pipelines lacking secrets; case-sensitivity mistakes (env.my_var vs env.MY_VAR); deploying the same glance.yml to a host missing the variable.","solutions":["Export the variable before starting Glance: `export MY_VAR=...` or add it to the systemd unit / compose environment.","Check exact spelling and case of the variable name inside {{ env.X }}.","Use `glance config:print` in the target environment to verify substitution works.","Alternatively switch to {{ secret.NAME }} with a file under /run/secrets for container deployments."],"exampleFix":"# docker-compose.yml (before)\nservices:\n  glance:\n    environment:\n      - TZ=${TZ}\n\n# after — pass the referenced variable into the container\nservices:\n  glance:\n    environment:\n      - TZ=${TZ}\n      - MY_VAR=${MY_VAR}","handlingStrategy":"validation","validationCode":"set -e\n: \"${GLANCE_HOST:?}\" \"${GLANCE_TOKEN:?}\"   # expands to: GLANCE_TOKEN: parameter null or not set\n# or enumerate every referenced var:\nfor var in $(grep -oE '\\{\\{ *env\\.[A-Za-z_][A-Za-z0-9_]* *\\}\\}' glance.yml | sed -E 's/.*env\\.([A-Za-z0-9_]+).*/\\1/'); do\n  printenv \"$var\" >/dev/null || { echo \"missing: $var\"; exit 1; }\ndone","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pass all referenced env vars explicitly in systemd Environment= or compose environment.","Remember empty-but-set is valid; unset is the failure — don't confuse the two when debugging.","Use `glance config:print` in the deploy environment to confirm substitution."],"tags":["config","environment","variables","deployment"],"backgroundTag":null,"analyzedSha":"91324e8de762702e97b0ac5c8e36271d644d8642","analyzedAt":"2026-08-15T14:12:54.279Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}