{"record":{"id":"218ea9cc1258a923","repo":"Tencent/WeKnora","slug":"create-verification-request-failed-w","errorCode":null,"errorMessage":"create verification request failed: %w","messagePattern":"create verification request failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/application/service/weknoracloud.go","lineNumber":63,"sourceCode":"\tif err := s.verifyCredentials(ctx, appID, appSecret); err != nil {\n\t\treturn fmt.Errorf(\"credential verification failed: %w\", err)\n\t}\n\n\ttenantID := types.MustTenantIDFromContext(ctx)\n\treturn s.updateTenantCredentials(ctx, tenantID, appID, appSecret)\n}\n\n// verifyCredentials 向 WeKnoraCloud /api/v1/health 发送带签名头的 GET。\n//\n// 注意：health 一般为探活接口，远端常不校验 APPID/SECRET 或签名；HTTP 200 通常只表示\n// 「网关/服务可达」，不能严格证明凭证有效。若需强校验，应改为调用必须鉴权的业务接口。\nfunc (s *weKnoraCloudService) verifyCredentials(ctx context.Context, appID, appSecret string) error {\n\tbaseURL := strings.TrimRight(provider.WeKnoraCloudBaseURL, \"/\")\n\thealthURL := baseURL + \"/api/v1/health\"\n\n\treq, err := http.NewRequestWithContext(ctx, http.MethodGet, healthURL, nil)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"create verification request failed: %w\", err)\n\t}\n\n\trequestID := fmt.Sprintf(\"verify-%d\", time.Now().UnixNano())\n\tsignHeaders := modelsutils.Sign(appID, appSecret, requestID, \"{}\")\n\tfor k, v := range signHeaders {\n\t\treq.Header.Set(k, v)\n\t}\n\n\tlogger.Infof(ctx, \"credential verification request: method=GET url=%s app_id=%s request_id=%s \",\n\t\thealthURL, appID, requestID)\n\n\tclientCfg := utils.DefaultSSRFSafeHTTPClientConfig()\n\tclientCfg.Timeout = 10 * time.Second\n\tclient := utils.NewSSRFSafeHTTPClient(clientCfg)\n\tresp, err := client.Do(req)\n\tif err != nil {\n\t\tlogger.Warnf(ctx, \"credential verification HTTP failed: url=%s err=%v\", healthURL, err)\n\t\treturn fmt.Errorf(\"service unreachable: %w\", err)","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/application/service/weknoracloud.go#L45-L81","documentation":"verifyCredentials builds a GET request to the WeKnora Cloud /api/v1/health endpoint with http.NewRequestWithContext. If request construction fails (almost always a malformed URL, e.g. an empty or invalid WeKnoraCloudBaseURL), the error is wrapped as 'create verification request failed: %w'.","triggerScenarios":"SaveCredentials -> verifyCredentials where baseURL is empty, contains control characters, or is otherwise not a parseable URL, making http.NewRequestWithContext return an error.","commonSituations":"WeKnoraCloudBaseURL not configured (empty string yields URL \"/api/v1/health\" which fails to parse); config value contains spaces/newlines; mis-templated env var (literal \"${...}\" left unresolved).","solutions":["Set provider.WeKnoraCloudBaseURL to a valid absolute https:// URL before saving credentials.","Check the config/env source for unresolved placeholders or stray whitespace and trim/expand them.","Validate the base URL at startup (url.Parse) so misconfiguration is caught early, not at credential save time.","Print the composed healthURL (without secrets) in debug logs to spot malformed composition."],"exampleFix":"// before\nbaseURL := cfg.WeKnoraCloudBaseURL // \"\" -> parse error\n// after\nif u, err := url.Parse(cfg.WeKnoraCloudBaseURL); err != nil || u.Scheme == \"\" || u.Host == \"\" {\n\treturn errors.New(\"WeKnoraCloudBaseURL must be an absolute http(s) URL\")\n}\nbaseURL := strings.TrimRight(cfg.WeKnoraCloudBaseURL, \"/\")","handlingStrategy":"validation","validationCode":"u, err := url.Parse(strings.TrimSpace(baseURL))\nif err != nil || u.Scheme == \"\" || u.Host == \"\" {\n\treturn fmt.Errorf(\"invalid WeKnoraCloudBaseURL %q: %w\", baseURL, err)\n}","typeGuard":null,"tryCatchPattern":"if err := svc.SaveCredentials(ctx, appID, appSecret); err != nil {\n\tif strings.Contains(err.Error(), \"create verification request failed\") {\n\t\t// baseURL is malformed; block save and ask for a valid https URL\n\t\treturn configError(\"WeKnoraCloudBaseURL\", err)\n\t}\n\treturn err\n}","preventionTips":["Validate baseURL with url.Parse at configuration load, not at request time.","Resolve env placeholders before use; reject literal \"${...}\" values.","Trim trailing slashes and whitespace from configured URLs.","Require https:// scheme in config validation."],"tags":["weknora-cloud","http","url","config"],"backgroundTag":"invalid-url","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}