{"record":{"id":"7fbdfe2e4c757b62","repo":"Tencent/WeKnora","slug":"invalid-appid-or-appsecret-http-d","errorCode":null,"errorMessage":"invalid APPID or APPSECRET (HTTP %d)","messagePattern":"invalid APPID or APPSECRET \\(HTTP (.+?)\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/application/service/weknoracloud.go","lineNumber":86,"sourceCode":"\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)\n\t}\n\tdefer resp.Body.Close()\n\n\tif resp.StatusCode == http.StatusUnauthorized || resp.StatusCode == http.StatusForbidden {\n\t\treturn fmt.Errorf(\"invalid APPID or APPSECRET (HTTP %d)\", resp.StatusCode)\n\t}\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn fmt.Errorf(\"invalid response status code: %d\", resp.StatusCode)\n\t}\n\treturn nil\n}\n\n// CheckStatus 检查 WeKnoraCloud 凭证是否可正常解密\nfunc (s *weKnoraCloudService) CheckStatus(ctx context.Context) (*types.WeKnoraCloudStatusResult, error) {\n\ttenantID := types.MustTenantIDFromContext(ctx)\n\n\ttenant, err := s.tenantRepo.GetTenantByID(ctx, tenantID)\n\tif err != nil || tenant == nil {\n\t\treturn &types.WeKnoraCloudStatusResult{HasModels: false, NeedsReinit: false}, nil\n\t}\n\n\tcreds := tenant.Credentials.GetWeKnoraCloud()\n\tif creds == nil {","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/application/service/weknoracloud.go#L68-L104","documentation":"When the WeKnora Cloud health endpoint responds with HTTP 401 or 403, verifyCredentials concludes the APPID/APPSECRET pair is invalid and returns 'invalid APPID or APPSECRET (HTTP %d)'. This is an application-level rejection of the credentials, not a transport failure.","triggerScenarios":"SaveCredentials called with credentials the server rejects: wrong APPID, wrong APPSECRET, revoked/expired credentials, or signature headers (modelsutils.Sign with a generated requestID) the server refuses to authenticate.","commonSituations":"Copy-paste errors introducing whitespace or truncating the secret; credentials rotated on the server side while the app still holds old ones; signing scheme/requestID format mismatch after a server upgrade; using credentials from a different WeKnora Cloud tenant.","solutions":["Re-enter APPID and APPSECRET exactly as issued (watch for trailing whitespace/newlines).","Regenerate credentials in the WeKnora Cloud console if they may have been revoked or rotated.","Confirm the Sign helper's headers and requestID format match what the server currently expects (check for version drift).","Verify you're authenticating against the correct environment (staging credentials vs production base URL).","If 403 persists with valid-looking credentials, check IP allowlisting or permission scope on the cloud side."],"exampleFix":"// before\nappSecret := \"sk-abc123 \" // trailing space/newline from paste\n// after\nappSecret := strings.TrimSpace(cfg.AppSecret)\nif err := svc.SaveCredentials(ctx, strings.TrimSpace(appID), appSecret); err != nil { ... }","handlingStrategy":"validation","validationCode":"if strings.TrimSpace(appID) == \"\" || strings.TrimSpace(appSecret) == \"\" {\n\treturn errors.New(\"APPID and APPSECRET must be non-empty\")\n}\n// optionally pre-verify against /api/v1/health with the same Sign headers before save","typeGuard":null,"tryCatchPattern":"if err := svc.SaveCredentials(ctx, appID, appSecret); err != nil {\n\tif strings.Contains(err.Error(), \"invalid APPID or APPSECRET\") {\n\t\t// do not retry with same creds; prompt user to re-enter them\n\t\treturn reauthError(err)\n\t}\n\treturn err\n}","preventionTips":["Trim pasted credentials; invisible whitespace is the top cause of 401s.","Re-copy credentials after any rotation on the cloud side.","Keep the Sign helper's header/requestID scheme in sync with server upgrades.","Confirm environment pairing (staging creds vs production URL).","Never blind-retry this error; it is deterministic for the given credentials."],"tags":["weknora-cloud","authentication","credentials","http-401","http-403"],"backgroundTag":"invalid-credentials","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}