{"record":{"id":"90071502e4971db4","repo":"JanDeDobbeleer/oh-my-posh","slug":"failed-to-read-themes-directory-s-w","errorCode":null,"errorMessage":"failed to read themes directory %s: %w","messagePattern":"failed to read themes directory (.+?): %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/config/data.go","lineNumber":50,"sourceCode":"\tDataVersionKey  = \"version\"\n\tDataEnvKey      = \"env\"\n\tDataSegmentsKey = \"segments\"\n)\n\n// ThemeFileExtensions is every extension a bundled theme file is recognized\n// by: mirrors website/export_themes.mjs's THEME_EXTENSIONS, the third copy of\n// this list living outside this repo's Go code.\nvar ThemeFileExtensions = []string{\".omp.json\", \".omp.toml\", \".omp.yaml\"}\n\n// ThemeFiles enumerates the theme files in dir, sorted so a caller merging or\n// comparing across all of them (cli's --themes merge mode, prompt's\n// golden-fixture harness) gets a deterministic order - for the merge mode\n// specifically, so mergeRichest's first-seen tie-break consistently favors\n// the alphabetically first theme.\nfunc ThemeFiles(dir string) ([]string, error) {\n\tentries, err := os.ReadDir(dir)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to read themes directory %s: %w\", dir, err)\n\t}\n\n\tvar files []string\n\n\tfor _, entry := range entries {\n\t\tif entry.IsDir() {\n\t\t\tcontinue\n\t\t}\n\n\t\tname := entry.Name()\n\n\t\tfor _, ext := range ThemeFileExtensions {\n\t\t\tif strings.HasSuffix(name, ext) {\n\t\t\t\tfiles = append(files, filepath.Join(dir, name))\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/JanDeDobbeleer/oh-my-posh/blob/0976794618c5ed95de0985dded50de1b4dc914cb/src/config/data.go#L32-L68","documentation":"ThemeFiles(dir) lists theme files in a directory for the config data merge feature. If os.ReadDir fails (directory missing, no permissions, wrong path), the OS error is wrapped with this message so callers know the themes directory itself could not be read.","triggerScenarios":"Passing a nonexistent or non-directory path as the themes directory, pointing at a path without read permission, or a misconfigured environment flag supplying the wrong dir.","commonSituations":"Typo in the themes path, running from a different working directory than assumed, Docker/CI containers missing the themes directory, or permission-restricted install locations.","solutions":["Verify the directory path exists: ls <dir>","Use the correct built-in themes location or an absolute path","Fix file permissions (chmod/chown) so the current user can read the directory","Check the flag/env var supplying the directory for typos"],"exampleFix":"// before\noh-my-posh config export --themes-dir ./themnes\n// after\noh-my-posh config export --themes-dir ./themes","handlingStrategy":"try-catch","validationCode":"stat, err := os.Stat(dir)\nif err != nil || !stat.IsDir() {\n    return fmt.Errorf(\"themes directory %s is missing or not a directory\", dir)\n}","typeGuard":"func isReadableDir(path string) bool {\n    info, err := os.Stat(path)\n    return err == nil && info.IsDir()\n}","tryCatchPattern":"files, err := config.ThemeFiles(dir)\nif err != nil && strings.Contains(err.Error(), \"failed to read themes directory\") {\n    log.Fatalf(\"themes dir %q unreadable: %v\", dir, errors.Unwrap(err))\n}","preventionTips":["Use absolute paths for theme directories","Check the directory exists in CI/containers before running","Fix read permissions after copying themes as root","Verify flags/env vars supplying the dir for typos"],"tags":["filesystem","io","themes"],"backgroundTag":"directory-not-found","analyzedSha":"0976794618c5ed95de0985dded50de1b4dc914cb","analyzedAt":"2026-08-31T23:41:19.708Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}