googleapis/mcp-toolbox · error

invalid page URL: %w

Error message

invalid page URL: %w

What it means

validateFHIRPageURL parses a caller-provided pagination URL with url.Parse before following it. This error means the page URL string is not a syntactically valid URL at all (url.Parse returned an error). The library throws it to avoid blindly issuing requests to garbage or attacker-controlled strings passed as FHIR next-page tokens.

Source

Thrown at internal/sources/cloudhealthcare/cloud_healthcare.go:327

	if len(v) < 2 || v[0] != 'v' {
		return false
	}
	// The character after 'v' must be a digit '1'-'9'
	if v[1] < '1' || v[1] > '9' {
		return false
	}
	for i := 2; i < len(v); i++ {
		if !isAlphanumeric(v[i]) {
			return false
		}
	}
	return true
}

func (s *Source) validateFHIRPageURL(pageURL string) (string, error) {
	parsed, err := url.Parse(pageURL)
	if err != nil {
		return "", fmt.Errorf("invalid page URL: %w", err)
	}

	if parsed.Scheme != "https" {
		return "", fmt.Errorf("URL scheme must be https, got %q", parsed.Scheme)
	}

	parsed.Host = strings.ToLower(parsed.Host)
	host := parsed.Host
	if h, _, err := net.SplitHostPort(host); err == nil {
		host = h
	}
	if _, ok := allowedFHIRHosts[host]; !ok {
		return "", fmt.Errorf("URL host must be an allowed FHIR host, got %q", host)
	}

	// Clean and split path
	cleanPath := path.Clean(parsed.Path)
	// Truncate leading and trailing slashes for easier splitting

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Pass the page URL exactly as it appeared in the previous response's links.next field — do not truncate or re-encode it
  2. Ensure the parameter is a full URL, not the opaque page token from a different API
  3. Strip whitespace/control characters before passing the URL
  4. If constructing programmatically, build with url.URL struct or url.BuildQuery and String() to guarantee validity

Example fix

// before
nextURL := strings.TrimSpace(rawLink)
resp, err := source.FHIRFetchPage(ctx, nextURL[1:]) // accidentally sliced
// after
nextURL := strings.TrimSpace(rawLink)
if _, err := url.Parse(nextURL); err != nil {
    return fmt.Errorf("page link from prior response is malformed: %w", err)
}
resp, err := source.FHIRFetchPage(ctx, nextURL)
Defensive patterns

Strategy: validation

Validate before calling

function isValidPageURL(u) { try { const p = new URL(u); return p.protocol === 'https:'; } catch { return false; } }

Try / catch

try {
  const page = await source.FHIRFetchPage(ctx, nextURL);
} catch (e) {
  if (/invalid page URL/.test(e.message)) {
    console.error('Page link corrupted, restart pagination from first page');
    return startFreshPagination();
  }
  throw e;
}

Prevention

When it happens

Trigger: FHIRFetchPage is given a nextPageToken/pageUrl parameter that is empty-with-garbage, contains control characters, or otherwise fails url.Parse (e.g. "http://[::1" with an unterminated bracket).

Common situations: An LLM/caller hands back a truncated or mangled page URL extracted from a previous response; a page token is confused with a full URL; shell/JSON escaping corrupts the URL (embedded spaces or newlines are usually tolerated by url.Parse, but malformed IPv6 brackets are not).

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05). Data as JSON: /api/errors/23b88f3978c01415. Report an issue: GitHub.