{"record":{"id":"1d70661d136b9edc","repo":"Tencent/WeKnora","slug":"invalid-api-base-url-w","errorCode":null,"errorMessage":"invalid api_base_url: %w","messagePattern":"invalid api_base_url: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/im/feishu/adapter.go","lineNumber":100,"sourceCode":"\t\tappID:             appID,\n\t\tappSecret:         appSecret,\n\t\tverificationToken: verificationToken,\n\t\tencryptKey:        encryptKey,\n\t\tapiBaseURL:        apiBaseURL,\n\t}, nil\n}\n\n// validateAPIBaseURL checks that a custom Feishu/Lark API base URL uses an\n// http(s) scheme and passes SSRF validation. Empty or the region default is\n// allowed without further checks. Mirrors wecom.validateEndpointURL but allows\n// plain http for internal-network reverse proxies that terminate TLS at nginx.\nfunc validateAPIBaseURL(endpoint, defaultEndpoint string) error {\n\tif endpoint == \"\" || endpoint == defaultEndpoint {\n\t\treturn nil\n\t}\n\tu, err := url.Parse(endpoint)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"invalid api_base_url: %w\", err)\n\t}\n\tif u.Scheme != \"http\" && u.Scheme != \"https\" {\n\t\treturn fmt.Errorf(\"api_base_url must use http(s):// scheme, got %s://\", u.Scheme)\n\t}\n\tif err := utils.ValidateURLForSSRF(endpoint); err != nil {\n\t\treturn fmt.Errorf(\"%w (for private deployments on internal networks, add the hostname to SSRF_WHITELIST)\", err)\n\t}\n\treturn nil\n}\n\n// api builds an Open Platform API URL on this adapter's cloud. path is a format\n// string beginning with \"/open-apis/\"; args fill its verbs.\nfunc (a *Adapter) api(path string, args ...any) string {\n\treturn a.apiBaseURL + fmt.Sprintf(path, args...)\n}\n\n// startStreamReaper starts a background goroutine (once) that periodically\n// removes orphaned stream entries from feishuStreams. This prevents memory","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/im/feishu/adapter.go#L82-L118","documentation":"Feishu's validateAPIBaseURL allows a custom api_base_url for private deployments, but first parses it with url.Parse. This error wraps any url.Parse failure, meaning the configured api_base_url is not a syntactically valid URL.","triggerScenarios":"NewAdapter called with a custom endpoint (non-empty and different from the default) that url.Parse rejects — e.g. containing invalid characters, a bare '%' or malformed percent-encoding, or control characters.","commonSituations":"Copy-pasting a URL with trailing spaces/quotes or invisible characters; missing scheme typos that produce unparseable input; shell/env escaping introducing stray characters.","solutions":["Fix the wrapped url.Parse error — validate the string with net/url.Parse in a quick test to see the exact problem.","Re-enter the api_base_url cleanly, e.g. https://open.feishu.internal, without quotes or stray whitespace.","Leave api_base_url empty to use the default endpoint if a custom one isn't actually needed."],"exampleFix":"// before\napi_base_url: \"https://open.feishu.cn/%zz\"\n// after\napi_base_url: \"https://open.feishu.cn\"","handlingStrategy":"validation","validationCode":"if endpoint != \"\" {\n    if _, err := url.Parse(endpoint); err != nil {\n        return fmt.Errorf(\"api_base_url is not a valid URL: %w\", err)\n    }\n}","typeGuard":"func isParseableURL(s string) bool { _, err := url.Parse(s); return err == nil }","tryCatchPattern":"if err := validateAPIBaseURL(endpoint, defaultEndpoint); err != nil {\n    if strings.HasPrefix(err.Error(), \"invalid api_base_url\") {\n        return fmt.Errorf(\"fix api_base_url syntax: %w\", err)\n    }\n    return err\n}","preventionTips":["Trim whitespace and quotes from config-provided URLs before storing.","Test custom endpoints with url.Parse in a preflight check.","Leave api_base_url empty when the default endpoint suffices.","Check for stray characters introduced by shell or env escaping."],"tags":["url","config","feishu"],"backgroundTag":"invalid-url","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}