JanDeDobbeleer/oh-my-posh · error

font path must be a valid URL

Error message

font path must be a valid URL

What it means

The font download step validates the font URL before fetching. `url.Parse` failed, or the parsed URL's scheme is not `https`, so download refuses to continue. Only HTTPS remote font locations are accepted; local paths or http:// URLs are rejected.

Source

Thrown at src/cli/font/download.go:31

	"github.com/jandedobbeleer/oh-my-posh/src/cache"
	"github.com/jandedobbeleer/oh-my-posh/src/cli/ui"
	"github.com/jandedobbeleer/oh-my-posh/src/runtime/http"
)

// download fetches a font zip, reporting how much has arrived so a caller can draw a bar. report
// may be nil, which is what the DSC path and the tests pass.
func download(fontURL string, report func(fraction float64)) ([]byte, error) {
	if zipPath, OK := cache.Device.Get[string](fontURL); OK {
		if b, err := os.ReadFile(zipPath); err == nil {
			return b, nil
		}
	}

	// validate if we have a local file
	u, err := url.Parse(fontURL)
	if err != nil || u.Scheme != "https" {
		return nil, errors.New("font path must be a valid URL")
	}

	var b []byte
	if b, err = getRemoteFile(fontURL, report); err != nil {
		return nil, err
	}

	if !isZipFile(b) {
		return nil, fmt.Errorf("%s is not a valid zip file", fontURL)
	}

	fileName := path.Base(fontURL)

	zipPath := filepath.Join(os.TempDir(), fileName)
	tempFile, err := os.Create(zipPath)
	defer func() {
		_ = tempFile.Close()
	}()

View on GitHub (pinned to 0976794618)

Solutions

  1. Provide a full https:// URL to the font archive, e.g. https://github.com/.../font.zip.
  2. If you have a local file, install it manually or serve it over HTTPS — the downloader does not accept local paths.
  3. Fix scheme typos (htp, http) to https.
  4. Verify the URL parses by checking it has scheme and host before passing it in.

Example fix

// before
err := download.Install(env, "~/Downloads/CascadiaCode.zip", nil)
// after
err := download.Install(env, "https://github.com/microsoft/cascadia-code/releases/download/v2404.23/CascadiaCode-2404.23.zip", nil)
Defensive patterns

Strategy: validation

Validate before calling

u, err := url.Parse(fontURL)
if err != nil || u.Scheme != "https" || u.Host == "" {
    return fmt.Errorf("font location must be an https URL, got %q", fontURL)
}

Type guard

func isHTTPSURL(s string) bool {
    u, err := url.Parse(s)
    return err == nil && u.Scheme == "https" && u.Host != ""
}

Try / catch

asset, err := download.Install(env, fontURL, report)
if err != nil && strings.Contains(err.Error(), "must be a valid URL") {
    return fmt.Errorf("%q is not an https URL; pass the release download link, not a local file", fontURL)
}

Prevention

When it happens

Trigger: Calling download (via Download or Install) with a fontURL that is a local file path (`~/Downloads/font.zip`, `C:\fonts\x.zip`), a relative path, an `http://` URL, or a malformed string that url.Parse cannot handle.

Common situations: Passing an already-downloaded zip instead of a URL; using an internal mirror served over plain http; typo'd URL (missing scheme, `htps://`); a config value where a URL was expected but a filesystem path was given.

Related errors


AI-assisted analysis of JanDeDobbeleer/oh-my-posh@0976794618 (2026-08-31). Data as JSON: /api/errors/f894160af5145897. Report an issue: GitHub.