usememos/memos · warning

invalid URL format

Error message

invalid URL format

What it means

validateURL in internal/httpgetter fails at url.Parse: the string cannot be parsed as a URL at all (Go's parser is lenient, so this usually means control characters, spaces in the scheme, or a completely malformed input). This runs before scheme, host, and IP checks.

Source

Thrown at internal/httpgetter/html_meta.go:111

			return nil, errors.Wrapf(ErrInternalIP, "host=%s, ip=%s", host, ip.String())
		}
		ips = append(ips, ip)
	}
	if len(ips) == 0 {
		return nil, errors.New("hostname resolved to no addresses")
	}

	return ips, nil
}

func isInternalIP(ip net.IP) bool {
	return ip.IsLoopback() || ip.IsPrivate() || ip.IsLinkLocalUnicast() || ip.IsUnspecified()
}

func validateURL(urlStr string) error {
	u, err := url.Parse(urlStr)
	if err != nil {
		return errors.New("invalid URL format")
	}

	if u.Scheme != "http" && u.Scheme != "https" {
		return errors.New("only http/https protocols are allowed")
	}

	host := u.Hostname()
	if host == "" {
		return errors.New("empty hostname")
	}

	if ip := net.ParseIP(host); ip != nil && isInternalIP(ip) {
		return errors.Wrap(ErrInternalIP, ip.String())
	}

	return nil
}

View on GitHub (pinned to 14d757ce1f)

Solutions

  1. Sanitize/trim the URL string, remove control characters, ensure valid percent-encoding
  2. Always include scheme and host: `https://example.com/path`
  3. Validate with url.Parse on the client side before submitting

Example fix

// before
GetHTMLMeta("example.com/page\x00")
// after
GetHTMLMeta("https://example.com/page")
Defensive patterns

Strategy: validation

Validate before calling

// Normalize + parse before fetching
func normalizeURL(raw string) (string, error) {
  raw = strings.TrimSpace(raw)
  raw = strings.Map(func(r rune) rune { if r < 0x20 { return -1 }; return r }, raw) // strip control chars
  u, err := url.Parse(raw)
  if err != nil { return "", err }
  if u.Host == "" { return "", errors.New("missing host") }
  return u.String(), nil
}

Try / catch

// Wrap fetch and treat URL validation failures as user-input errors
if _, err := getter.GetHTMLMeta(raw); err != nil {
  if strings.Contains(err.Error(), "invalid URL format") {
    return status.Errorf(codes.InvalidArgument, "not a valid URL: %s", raw)
  }
  return err
}

Prevention

When it happens

Trigger: Passing a bare string like `example.com/page` (no scheme can still parse, but inputs with control chars/invalid escapes fail), URLs with embedded control characters or malformed percent-encoding, or non-URL text accidentally submitted as a link.

Common situations: Users pasting text instead of a URL into a memo that gets auto-detected as a link; frontends not validating input before calling the preview API; copy-paste introducing invisible control characters (e.g. from PDFs or chat apps).

Related errors


AI-assisted analysis of usememos/memos@14d757ce1f (2026-08-15). Data as JSON: /api/errors/948e6d2f7824151b. Report an issue: GitHub.