{"record":{"id":"5f7785d08957ba54","repo":"charmbracelet/glow","slug":"unable-to-get-cache-dir-w","errorCode":null,"errorMessage":"unable to get cache dir: %w","messagePattern":"unable to get cache dir: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"log.go","lineNumber":16,"sourceCode":"package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"path/filepath\"\n\n\t\"github.com/charmbracelet/log\"\n\tgap \"github.com/muesli/go-app-paths\"\n)\n\nfunc getLogFilePath() (string, error) {\n\tdir, err := gap.NewScope(gap.User, \"glow\").CacheDir()\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"unable to get cache dir: %w\", err)\n\t}\n\treturn filepath.Join(dir, \"glow.log\"), nil\n}\n\nfunc setupLog() (func() error, error) {\n\tlog.SetOutput(io.Discard)\n\t// Log to file, if set\n\tlogFile, err := getLogFilePath()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif err := os.MkdirAll(filepath.Dir(logFile), 0o755); err != nil { //nolint:gosec\n\t\t// log disabled\n\t\treturn func() error { return nil }, nil //nolint:nilerr\n\t}\n\tf, err := os.OpenFile(logFile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0o644) //nolint:gosec\n\tif err != nil {\n\t\t// log disabled","sourceCodeStart":1,"sourceCodeEnd":34,"githubUrl":"https://github.com/charmbracelet/glow/blob/e3970c813d93da1ea84edfca90c289d9afb82242/log.go#L1-L34","documentation":"On startup glow resolves a log-file directory with go-app-paths (gap.NewScope(gap.User, \"glow\").CacheDir(), i.e. ~/.cache/glow on Linux). This error means the user cache directory could not be determined - typically because HOME and XDG_CACHE_HOME are unset or unusable. main() treats it as fatal: it prints the error and exits 1, so glow does not start at all.","triggerScenarios":"HOME unset and XDG_CACHE_HOME unset (gap cannot compute the cache path); HOME pointing to a path that cannot be resolved; running in an environment where neither variable exists.","commonSituations":"Docker/OCI scratch or distroless images, systemd units without Environment=\"HOME=...\", cron jobs, CI runners that scrub the environment, minimal sandboxes.","solutions":["Set HOME to a writable directory: export HOME=/tmp","Or set XDG_CACHE_HOME=/tmp/cache on Linux so the cache dir resolves","For service units, add Environment=\"HOME=/var/lib/glow\" to the unit file","Verify writability afterwards: mkdir -p ~/.cache/glow"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"func cacheDirResolvable() bool {\n\tif dir := os.Getenv(\"XDG_CACHE_HOME\"); dir != \"\" {\n\t\tfi, err := os.Stat(dir)\n\t\treturn err == nil && fi.IsDir()\n\t}\n\treturn os.Getenv(\"HOME\") != \"\"\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always define HOME or XDG_CACHE_HOME in containers, services and cron contexts","Smoke-test CLI binaries in the same scrubbed environment where they will run","Treat logging setup as optional in wrappers if logs are not required"],"tags":["environment","xdg","filesystem","startup"],"backgroundTag":null,"analyzedSha":"e3970c813d93da1ea84edfca90c289d9afb82242","analyzedAt":"2026-08-15T22:50:54.304Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}