{"record":{"id":"f894160af5145897","repo":"JanDeDobbeleer/oh-my-posh","slug":"font-path-must-be-a-valid-url","errorCode":null,"errorMessage":"font path must be a valid URL","messagePattern":"font path must be a valid URL","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cli/font/download.go","lineNumber":31,"sourceCode":"\n\t\"github.com/jandedobbeleer/oh-my-posh/src/cache\"\n\t\"github.com/jandedobbeleer/oh-my-posh/src/cli/ui\"\n\t\"github.com/jandedobbeleer/oh-my-posh/src/runtime/http\"\n)\n\n// download fetches a font zip, reporting how much has arrived so a caller can draw a bar. report\n// may be nil, which is what the DSC path and the tests pass.\nfunc download(fontURL string, report func(fraction float64)) ([]byte, error) {\n\tif zipPath, OK := cache.Device.Get[string](fontURL); OK {\n\t\tif b, err := os.ReadFile(zipPath); err == nil {\n\t\t\treturn b, nil\n\t\t}\n\t}\n\n\t// validate if we have a local file\n\tu, err := url.Parse(fontURL)\n\tif err != nil || u.Scheme != \"https\" {\n\t\treturn nil, errors.New(\"font path must be a valid URL\")\n\t}\n\n\tvar b []byte\n\tif b, err = getRemoteFile(fontURL, report); err != nil {\n\t\treturn nil, err\n\t}\n\n\tif !isZipFile(b) {\n\t\treturn nil, fmt.Errorf(\"%s is not a valid zip file\", fontURL)\n\t}\n\n\tfileName := path.Base(fontURL)\n\n\tzipPath := filepath.Join(os.TempDir(), fileName)\n\ttempFile, err := os.Create(zipPath)\n\tdefer func() {\n\t\t_ = tempFile.Close()\n\t}()","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/JanDeDobbeleer/oh-my-posh/blob/0976794618c5ed95de0985dded50de1b4dc914cb/src/cli/font/download.go#L13-L49","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Provide a full https:// URL to the font archive, e.g. https://github.com/.../font.zip.","If you have a local file, install it manually or serve it over HTTPS — the downloader does not accept local paths.","Fix scheme typos (htp, http) to https.","Verify the URL parses by checking it has scheme and host before passing it in."],"exampleFix":"// before\nerr := download.Install(env, \"~/Downloads/CascadiaCode.zip\", nil)\n// after\nerr := download.Install(env, \"https://github.com/microsoft/cascadia-code/releases/download/v2404.23/CascadiaCode-2404.23.zip\", nil)","handlingStrategy":"validation","validationCode":"u, err := url.Parse(fontURL)\nif err != nil || u.Scheme != \"https\" || u.Host == \"\" {\n    return fmt.Errorf(\"font location must be an https URL, got %q\", fontURL)\n}","typeGuard":"func isHTTPSURL(s string) bool {\n    u, err := url.Parse(s)\n    return err == nil && u.Scheme == \"https\" && u.Host != \"\"\n}","tryCatchPattern":"asset, err := download.Install(env, fontURL, report)\nif err != nil && strings.Contains(err.Error(), \"must be a valid URL\") {\n    return fmt.Errorf(\"%q is not an https URL; pass the release download link, not a local file\", fontURL)\n}","preventionTips":["Always pass full https:// release URLs, never local file paths or plain-http mirrors","Validate scheme+host before calling install in scripts","For local font files, install manually instead of using the downloader"],"tags":["cli","font","url","validation","https"],"backgroundTag":"invalid-url-scheme","analyzedSha":"0976794618c5ed95de0985dded50de1b4dc914cb","analyzedAt":"2026-08-31T23:41:19.708Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}