wtfutil/wtf · error

invalid base URL: %w

Error message

invalid base URL: %w

What it means

devto Client.FetchArticles starts by parsing c.baseURL with url.Parse; if that fails the error is wrapped as 'invalid base URL'. This only happens when the configured base URL is not a valid URL string, which normally indicates bad construction of the Client rather than a network problem.

Source

Thrown at modules/devto/client.go:44

}

// NewClient creates a Client. Pass nil for httpClient to use http.DefaultClient.
// baseURL overrides the API endpoint (useful for testing); pass "" for the default.
func NewClient(httpClient *http.Client, baseURL string) *Client {
	if httpClient == nil {
		httpClient = http.DefaultClient
	}
	if baseURL == "" {
		baseURL = defaultBaseURL
	}
	return &Client{httpClient: httpClient, baseURL: baseURL}
}

// FetchArticles retrieves articles matching the given filters.
func (c *Client) FetchArticles(ctx context.Context, tag, username, state string, perPage int) ([]Article, error) {
	u, err := url.Parse(c.baseURL)
	if err != nil {
		return nil, fmt.Errorf("invalid base URL: %w", err)
	}

	q := u.Query()
	if tag != "" {
		q.Set("tag", tag)
	}
	if username != "" {
		q.Set("username", username)
	}
	if state != "" {
		q.Set("state", state)
	}
	if perPage > 0 {
		q.Set("per_page", fmt.Sprintf("%d", perPage))
	}
	u.RawQuery = q.Encode()

	req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil)

View on GitHub (pinned to bb838c1ccb)

Solutions

  1. Use the default DEV.to base URL (https://dev.to/api) unless overriding intentionally
  2. Validate the custom base URL with url.Parse before constructing the Client
  3. Print/log c.baseURL to spot stray characters or empty scheme

Example fix

// before
client := NewClient("http://dev.to/api/{bad url}")
// after
u, err := url.Parse("https://dev.to/api")
if err != nil {
    return err
}
client := NewClient(u.String())
Defensive patterns

Strategy: validation

Validate before calling

func validateBaseURL(raw string) error {
    if raw == "" {
        return errors.New("base URL is empty")
    }
    if _, err := url.Parse(raw); err != nil {
        return fmt.Errorf("invalid base URL %q: %w", raw, err)
    }
    return nil
}
if err := validateBaseURL(baseURL); err != nil { return err }

Try / catch

articles, err := client.FetchArticles(ctx, tag, user, state, perPage)
if err != nil {
    if strings.HasPrefix(err.Error(), "invalid base URL") {
        return fmt.Errorf("misconfigured devto client: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: url.Parse(c.baseURL) errors — e.g. baseURL contains control characters or an unparsable scheme — when NewClient was given a malformed override URL instead of the default DEV.to endpoint.

Common situations: Passing an empty-with-garbage or typo'd base URL override in tests or custom configuration; concatenating config values into the URL producing invalid characters.

Related errors


AI-assisted analysis of wtfutil/wtf@bb838c1ccb (2026-09-03). Data as JSON: /api/errors/e7148c266a3e2935. Report an issue: GitHub.