charmbracelet/glow · error · errMsg

error creating glamour renderer: %w

Error message

error creating glamour renderer: %w

What it means

Thrown while building the glamour.TermRenderer for the TUI pager (ui/pager.go:367-378). The style option comes from utils.GlamourStyle(cfg.GlamourStyle, isCode): built-in names and "auto" map to bundled styles, anything else becomes glamour.WithStylePath (or WithStylesFromJSONFile for code files, utils/utils.go:106). glamour.NewTermRenderer fails when that custom style cannot be loaded — missing name/path or a style file whose JSON is invalid. Note the config-file path is guarded by validateStyle (main.go:154-164), which stats the file but does not parse it, so malformed JSON slips past startup validation and only fails here.

Source

Thrown at ui/pager.go:377

	}

	isCode := !utils.IsMarkdownFile(m.currentDocument.Note)
	width := max(0, min(int(m.common.cfg.GlamourMaxWidth), m.viewport.Width())) //nolint:gosec
	if isCode {
		width = 0
	}

	options := []glamour.TermRendererOption{
		utils.GlamourStyle(m.common.cfg.GlamourStyle, isCode),
		glamour.WithWordWrap(width),
	}

	if m.common.cfg.PreserveNewLines {
		options = append(options, glamour.WithPreservedNewLines())
	}
	r, err := glamour.NewTermRenderer(options...)
	if err != nil {
		return "", fmt.Errorf("error creating glamour renderer: %w", err)
	}

	if isCode {
		markdown = utils.WrapCodeBlock(markdown, filepath.Ext(m.currentDocument.Note))
	}

	out, err := r.Render(markdown)
	if err != nil {
		return "", fmt.Errorf("error rendering markdown: %w", err)
	}

	if isCode {
		out = strings.TrimSpace(out)
	}

	// trim lines
	lines := strings.Split(out, "\n")

View on GitHub (pinned to e3970c813d)

Solutions

  1. Verify the style file parses: `jq . ~/path/to/style.json` (or switch to a built-in: auto, dark, light, notty, dracula, tokyo-night, pink) via `--style` or glow.yml.
  2. Confirm the path exists after ~ expansion (glow expands via utils.ExpandPath): `ls -l "$HOME/styles/my-theme.json"`.
  3. Unset a stale environment override: `unset GLAMOUR_STYLE`.
  4. If it persists, run `glow file.md` one-shot with the same style to reproduce outside the TUI and inspect the wrapped error from glamour.

Example fix

# before (~/.config/glow/glow.yml): file exists but is malformed JSON
style: ~/styles/my-theme.json

# after: valid built-in style, or fix the JSON with `jq . ~/styles/my-theme.json`
style: dark
Defensive patterns

Strategy: validation

Validate before calling

func styleLoadable(style string) bool {
	if style == "auto" || styles.DefaultStyles[style] != nil {
		return true
	}
	p := utils.ExpandPath(style)
	b, err := os.ReadFile(p)
	return err == nil && json.Valid(b)
}

// before building the renderer:
if !styleLoadable(m.common.cfg.GlamourStyle) {
	m.common.cfg.GlamourStyle = "auto"
}

Try / catch

r, err := glamour.NewTermRenderer(options...)
if err != nil {
	// retry once with the default style instead of failing the pager
	options[0] = glamour.WithStandardStyle("dark")
	if r, err = glamour.NewTermRenderer(options...); err != nil {
		return "", fmt.Errorf("error creating glamour renderer: %w", err)
	}
}

Prevention

When it happens

Trigger: A hand-edited custom style JSON with a syntax error (passes os.Stat in validateStyle, fails at renderer construction); `style = "solarized"` in glow.yml when no such file or bundled style exists; GLAMOUR_STYLE env var pointing at a moved/deleted file; glamour upgrades renaming or dropping a previously bundled style.

Common situations: Custom themes kept as JSON files that later get truncated or corrupted; configs shared across machines where the style path differs; version drift between the glow that authored the config and the currently installed glamour styles; CI environments with stale GLAMOUR_STYLE exported.

Related errors


AI-assisted analysis of charmbracelet/glow@e3970c813d (2026-08-15). Data as JSON: /api/errors/88e2353e95abf5c2. Report an issue: GitHub.