JanDeDobbeleer/oh-my-posh · error
failed to parse theme %s
Error message
failed to parse theme %s
What it means
recordThemeSanitized (used by `config export data --themes --sanitize`) loads a theme file with config.Load. If the resulting config has an empty Source — the loader failed to read or parse the file — it returns "failed to parse theme <path>". It means the theme file at that path could not be loaded as a valid oh-my-posh config.
Source
Thrown at src/cli/config_export_data.go:214
dataCmd.Flags().StringVar(&dataPath, "data", "",
"path to a template data file to seed the recording with, instead of the live environment")
dataCmd.Flags().StringVar(&themesDir, "themes", "",
"record every theme in this directory and merge them into one sanitized fixture, ignoring --config (requires --sanitize)")
exportCmd.AddCommand(dataCmd)
}
// recordThemeSanitized runs one theme's segments against the real environment,
// exactly as the single-config path above does, then returns its sanitized env
// and segment maps for merging. Each call gets its own fresh template cache
// (resetTemplateCache=true, below, drives render.Config's own
// template.ResetCache before template.Init) so one theme's Var/Maps never leak
// into the next theme's render, the same isolation prompt/golden_test.go's
// renderTheme relies on between themes.
func recordThemeSanitized(themePath string) (env, segments map[string]json.RawMessage, err error) {
cfg := config.Load(themePath)
if cfg.Source == "" {
return nil, nil, fmt.Errorf("failed to parse theme %s", themePath)
}
// --data seeds the writers with a fixture's own values before they render, so re-recording an
// existing file keeps what it was curated with and only adds what the format has since gained.
// Without it every theme would record whatever this machine happens to look like.
if _, err := render.Config(cfg, 120, true, func(flags *runtime.Flags) error {
return applyDataFile(flags, func(string) bool { return false })
}); err != nil {
return nil, nil, fmt.Errorf("failed to record theme %s: %w", themePath, err)
}
doc, err := buildDataDocument(cfg)
if err != nil {
return nil, nil, fmt.Errorf("failed to record theme %s: %w", themePath, err)
}
sanitized, err := sanitizeDataDocument(doc, cfg)
if err != nil {View on GitHub (pinned to 0976794618)
Solutions
- Open the named theme file and fix or remove it from the directory
- Validate the file parses (run `oh-my-posh config migrate --config <file>` or print with it) to see the underlying syntax error
- Check file permissions and that the file is not empty
- Point --themes at a directory containing only valid theme configs (e.g. the bundled themes/ folder)
Example fix
// before --themes ../my-mixed-dir # contains theme.json.bak // after --themes ../themes # only valid *.omp.json files
Defensive patterns
Strategy: validation
Validate before calling
// Go: verify the theme loads before batch-recording
var cfg = config.Load(path)
if cfg.Source == "" {
return fmt.Errorf("theme %s is not a valid config", path)
} Type guard
func themeLoads(path string) bool {
return config.Load(path).Source != ""
} Try / catch
env, segments, err := recordThemeSanitized(themePath)
if err != nil {
if strings.Contains(err.Error(), "failed to parse theme") {
fmt.Fprintf(os.Stderr, "skipping invalid theme: %v\n", err)
return nil // or fail fast, per policy
}
return err
} Prevention
- Point --themes at directories containing only valid theme configs
- Validate each theme with a quick `oh-my-posh print primary --config <file>` before batch runs
- Exclude editor backups and partial files (glob *.omp.json only)
- Check file permissions before recording across user directories
When it happens
Trigger: Running the --themes merge over a directory where one of the discovered files is unreadable, empty, or not a valid TOML/JSON/YAML config, so config.Load yields cfg.Source == "".
Common situations: Pointing --themes at a directory containing stray non-config files (README, partial JSON, editor backups like theme.json~); a truncated download; wrong file extension; permission errors on the file.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- unclosed section:
- key-value delimiter not found:
- failed to record theme %s: %w
- failed to sanitize theme %s: %w
- failed to parse data file: %w
AI-assisted analysis of JanDeDobbeleer/oh-my-posh@0976794618 (2026-08-31).
Data as JSON: /api/errors/f1e73b26982794b2.
Report an issue: GitHub.