{"record":{"id":"abf510e164188c13","repo":"chenhg5/cc-connect","slug":"yuanbao-sign-token-response-missing-data","errorCode":null,"errorMessage":"yuanbao: sign token response missing data","messagePattern":"yuanbao: sign token response missing data","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/yuanbao/sign.go","lineNumber":185,"sourceCode":"\t\t\t\tToken    string `json:\"token\"`\n\t\t\t\tBotID    string `json:\"bot_id\"`\n\t\t\t\tDuration int    `json:\"duration\"`\n\t\t\t\tProduct  string `json:\"product\"`\n\t\t\t\tSource   string `json:\"source\"`\n\t\t\t} `json:\"data\"`\n\t\t}\n\t\tif err := json.Unmarshal(respBody, &result); err != nil {\n\t\t\tlastErr = fmt.Errorf(\"yuanbao: parse response: %w\", err)\n\t\t\tcontinue\n\t\t}\n\t\tif result.Code == 10099 && attempt < maxRetries {\n\t\t\tcontinue\n\t\t}\n\t\tif result.Code != 0 {\n\t\t\treturn nil, fmt.Errorf(\"yuanbao: sign token error code=%d\", result.Code)\n\t\t}\n\t\tif result.Data == nil {\n\t\t\treturn nil, fmt.Errorf(\"yuanbao: sign token response missing data\")\n\t\t}\n\t\treturn &tokenData{\n\t\t\ttoken: result.Data.Token, botID: result.Data.BotID,\n\t\t\tduration: result.Data.Duration, product: result.Data.Product,\n\t\t\tsource: result.Data.Source,\n\t\t}, nil\n\t}\n\treturn nil, lastErr\n}\n\n// VerifyCredentials probes the sign-token API with app_key/app_secret and\n// returns the bot_id on success. Used by `cc-connect yuanbao setup` so users\n// see a clear error before the platform starts retrying on a background loop.\nfunc VerifyCredentials(appKey, appSecret, apiDomain, routeEnv string) (botID string, err error) {\n\tif strings.TrimSpace(appKey) == \"\" || strings.TrimSpace(appSecret) == \"\" {\n\t\treturn \"\", fmt.Errorf(\"yuanbao: bot_token is required (format: app_key:app_secret)\")\n\t}\n\tdata, err := fetchToken(appKey, appSecret, apiDomain, routeEnv)","sourceCodeStart":167,"sourceCodeEnd":203,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/yuanbao/sign.go#L167-L203","documentation":"The sign-token API returned code 0 (success) but the data object was null, so no token could be extracted. This is a defensive invariant check against an upstream contract violation: a success code with no payload. It is returned immediately without retry.","triggerScenarios":"result.Data == nil after json.Unmarshal of a code==0 response — upstream returned {\"code\":0} with data omitted/null, typically a partial failure or protocol bug on the sign service.","commonSituations":"Upstream service degradation where the API reports success but omits the payload; an API version change that renamed the data field; a proxy stripping or rewriting the response body.","solutions":["Capture the raw response body and report it to the yuanbao API team — code 0 with null data is a server-side contract violation.","Retry the token fetch manually; if persistent, treat the endpoint as unhealthy and fall back.","Verify no proxy/middleware is rewriting the JSON body between cc-connect and the sign service.","Check for upstream API version changes that may have renamed the data field and update the struct in sign.go."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":"func hasTokenData(resp *tokenEnvelope) bool { return resp != nil && resp.Code == 0 && resp.Data != nil }","tryCatchPattern":"td, err := fetchToken(...)\nif err != nil && strings.Contains(err.Error(), \"missing data\") {\n    // treat endpoint as unhealthy: fall back to cached token or alert\n}","preventionTips":["Report code-0-with-null-data occurrences to the upstream API team","Cache the last good token to survive transient upstream contract violations","Add an integration test asserting Data is non-nil on success responses"],"tags":["api","response-shape","invariant","upstream"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}