Tencent/WeKnora · error

api_base_url must use http(s):// scheme, got %s://

Error message

api_base_url must use http(s):// scheme, got %s://

What it means

For a custom (non-default) Feishu api_base_url, the scheme must be http or https. validateAPIBaseURL returns this error verbatim (no wrap) when u.Scheme is anything else — including empty, meaning the URL had no scheme at all.

Source

Thrown at internal/im/feishu/adapter.go:103

		encryptKey:        encryptKey,
		apiBaseURL:        apiBaseURL,
	}, nil
}

// validateAPIBaseURL checks that a custom Feishu/Lark API base URL uses an
// http(s) scheme and passes SSRF validation. Empty or the region default is
// allowed without further checks. Mirrors wecom.validateEndpointURL but allows
// plain http for internal-network reverse proxies that terminate TLS at nginx.
func validateAPIBaseURL(endpoint, defaultEndpoint string) error {
	if endpoint == "" || endpoint == defaultEndpoint {
		return nil
	}
	u, err := url.Parse(endpoint)
	if err != nil {
		return fmt.Errorf("invalid api_base_url: %w", err)
	}
	if u.Scheme != "http" && u.Scheme != "https" {
		return fmt.Errorf("api_base_url must use http(s):// scheme, got %s://", u.Scheme)
	}
	if err := utils.ValidateURLForSSRF(endpoint); err != nil {
		return fmt.Errorf("%w (for private deployments on internal networks, add the hostname to SSRF_WHITELIST)", err)
	}
	return nil
}

// api builds an Open Platform API URL on this adapter's cloud. path is a format
// string beginning with "/open-apis/"; args fill its verbs.
func (a *Adapter) api(path string, args ...any) string {
	return a.apiBaseURL + fmt.Sprintf(path, args...)
}

// startStreamReaper starts a background goroutine (once) that periodically
// removes orphaned stream entries from feishuStreams. This prevents memory
// leaks when EndStream is never called due to panics or pipeline errors.
func startStreamReaper() {
	startReaperOnce.Do(func() {

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Prefix the URL with https:// (or http:// for plaintext internal testing).
  2. Remember the check only applies to custom endpoints — leaving api_base_url empty avoids it entirely.
  3. If the scheme looks correct, check for leading whitespace which can make url.Parse yield an empty scheme.

Example fix

// before
api_base_url: "feishu.internal.example.com"
// after
api_base_url: "https://feishu.internal.example.com"
Defensive patterns

Strategy: validation

Validate before calling

u, err := url.Parse(endpoint)
if err == nil && u.Scheme != "http" && u.Scheme != "https" {
    return fmt.Errorf("api_base_url must start with https:// (got %q)", endpoint)
}

Type guard

func hasHTTPScheme(s string) bool {
    u, err := url.Parse(s)
    return err == nil && (u.Scheme == "http" || u.Scheme == "https")
}

Try / catch

if err := validateAPIBaseURL(endpoint, defaultEndpoint); err != nil {
    if strings.Contains(err.Error(), "must use http(s):// scheme") {
        return fmt.Errorf("prefix api_base_url with https://")
    }
    return err
}

Prevention

When it happens

Trigger: NewAdapter with api_base_url like "open.feishu.cn" (no scheme), "ftp://...", or "ws://..." while the value differs from the default endpoint.

Common situations: Omitting https:// when typing the internal Feishu gateway address; using ws:// or grpc:// schemes by analogy with other SDKs; config examples copied without the scheme.

Related errors


AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02). Data as JSON: /api/errors/283182d53016e774. Report an issue: GitHub.