charmbracelet/glow · warning

unable to parse url: %w

Error message

unable to parse url: %w

What it means

Thrown by readmeURL (url.go:43-49) when interpreting a CLI argument as a GitHub/GitLab README location: if the argument lacks an https:// prefix one is prepended, and then url.Parse must succeed. url.Parse only errors on structurally invalid URLs — control characters or spaces in the wrong places, invalid percent-escapes like %zz, or an invalid port. Note glow's caller (sourceFromArg, main.go:81-85) deliberately swallows this error and falls through to local-file handling, so in the shipped binary the visible effect is usually 'argument treated as a file path' rather than this message.

Source

Thrown at url.go:48

	switch {
	case strings.HasPrefix(path, protoGithub):
		if u := githubReadmeURL(path); u != nil {
			return readmeURL(u.String())
		}
		return nil, nil
	case strings.HasPrefix(path, protoGitlab):
		if u := gitlabReadmeURL(path); u != nil {
			return readmeURL(u.String())
		}
		return nil, nil
	}

	if !strings.HasPrefix(path, protoHTTPS) {
		path = protoHTTPS + path
	}
	u, err := url.Parse(path)
	if err != nil {
		return nil, fmt.Errorf("unable to parse url: %w", err)
	}

	switch {
	case u.Hostname() == githubURL.Hostname():
		return findGitHubREADME(u)
	case u.Hostname() == gitlabURL.Hostname():
		return findGitLabREADME(u)
	}

	return nil, nil
}

func githubReadmeURL(path string) *url.URL {
	path = strings.TrimPrefix(path, protoGithub)
	parts := strings.Split(path, "/")
	if len(parts) != 2 {
		// custom hostnames are not supported yet
		return nil

View on GitHub (pinned to e3970c813d)

Solutions

  1. Quote the argument and strip stray whitespace: `glow "github.com/charmbracelet/glow"`.
  2. Percent-encode literal percent signs: `%` → `%25` (e.g. `example.com/50%25off`).
  3. Fix or drop the malformed port/scheme portion of the URL.
  4. In code, pre-screen with url.ParseRequestURI or the repo's own isURL() (url.go:83) before calling readmeURL.

Example fix

# before
$ glow example.com/50%off
# unable to parse url: parse "https://example.com/50%off": invalid URL escape "%of"

# after
$ glow "example.com/50%25off"
Defensive patterns

Strategy: validation

Validate before calling

func looksLikeURL(path string) bool {
	if strings.ContainsAny(path, " \t\r\n") {
		return false
	}
	_, err := url.Parse(path)
	return err == nil
}

// only attempt README resolution when the screen passes:
if looksLikeURL(arg) {
	src, err := readmeURL(arg)
	_ = err // caller already falls through to file handling
}

Type guard

func isParseURLError(err error) bool {
	var ue *url.Error
	return errors.As(err, &ue) && ue.Op == "parse"
}

Try / catch

src, err := readmeURL(arg)
if err != nil {
	// not a usable URL: mirror main.go's behavior and continue
	// with local-file handling instead of aborting
	log.Debug("argument is not a parseable URL", "arg", arg, "error", err)
}

Prevention

When it happens

Trigger: `glow example.com/50%off` — invalid URL escape "%of"; an unquoted argument containing a space; a pasted URL with leading/trailing whitespace or an embedded newline; a malformed port segment such as `example.com:8o0x`.

Common situations: Unquoted shell arguments; URLs copied with invisible whitespace or newlines; literal percent signs in paths that were never percent-encoded; scripts passing unsanitized strings as the glow argument.

Understand the failure class

Related errors


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