charmbracelet/glow · error

invalid url: %s

Error message

invalid url: %s

What it means

findGitHubREADME extracts the owner and repo by cutting the URL path on the first '/' after trimming the leading slash: strings.Cut(strings.TrimPrefix(u.Path, "/"), "/"). If there is no separator — i.e. fewer than two path segments — ok is false and this error reports the whole URL. It is a pure URL-shape failure that happens before any network request.

Source

Thrown at github.go:17

package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"strings"
)

// findGitHubREADME tries to find the correct README filename in a repository using GitHub API.
func findGitHubREADME(u *url.URL) (*source, error) {
	owner, repo, ok := strings.Cut(strings.TrimPrefix(u.Path, "/"), "/")
	if !ok {
		return nil, fmt.Errorf("invalid url: %s", u.String())
	}

	type readme struct {
		DownloadURL string `json:"download_url"`
	}

	apiURL := fmt.Sprintf("https://api.%s/repos/%s/%s/readme", u.Hostname(), owner, repo)

	//nolint:bodyclose
	// it is closed on the caller
	res, err := http.Get(apiURL) //nolint: gosec,noctx
	if err != nil {
		return nil, fmt.Errorf("unable to get url: %w", err)
	}

	body, err := io.ReadAll(res.Body)
	if err != nil {
		return nil, fmt.Errorf("unable to read http response body: %w", err)

View on GitHub (pinned to e3970c813d)

Solutions

  1. Use the full repository URL: https://github.com/OWNER/REPO
  2. If building URLs in code, validate both segments are non-empty before invoking glow
  3. For a user/org page, navigate to an actual repo first

Example fix

# before
glow https://github.com/charmbracelet   # org page, no repo

# after
glow https://github.com/charmbracelet/glow
Defensive patterns

Strategy: type-guard

Type guard

func isGitHubRepoURL(u *url.URL) bool {
	if u == nil || (u.Host != "github.com" && !strings.HasSuffix(u.Host, ".github.com")) {
		return false
	}
	_, _, ok := strings.Cut(strings.TrimPrefix(u.Path, "/"), "/")
	return ok
}

if !isGitHubRepoURL(u) {
	return fmt.Errorf("expected https://github.com/OWNER/REPO, got %s", u)
}

Try / catch

src, err := findGitHubREADME(u)
if err != nil {
	var invErr *url.Error
	if strings.Contains(err.Error(), "invalid url") {
		// shape failure — retrying is pointless; re-prompt for a full repo URL
		return nil, fmt.Errorf("need owner/repo URL like https://github.com/OWNER/REPO: %w", err)
	}
	_ = invErr
	return nil, err
}

Prevention

When it happens

Trigger: Passing a bare host like https://github.com; a profile URL with a single segment like https://github.com/charmbracelet; trailing content that still leaves only one segment; URLs where the repo part is empty (https://github.com/owner/).

Common situations: Copy-pasting an incomplete URL from a trimmed tooltip; passing a user/org page instead of a repository; constructing URLs programmatically with an empty repo variable.

Related errors


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