{"record":{"id":"b31d937a58674c71","repo":"chenhg5/cc-connect","slug":"s-refresh-card-w","errorCode":null,"errorMessage":"%s: refresh card: %w","messagePattern":"(.+?): refresh card: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/feishu/card.go","lineNumber":78,"sourceCode":"\tmsgID := p.cardActionMsgIDs[sessionKey]\n\tp.cardActionMsgMu.Unlock()\n\n\tif msgID == \"\" {\n\t\treturn fmt.Errorf(\"%s: no tracked card messageID for session %q\", p.tag(), sessionKey)\n\t}\n\n\tcardJSON := renderCard(card, sessionKey)\n\treq := larkim.NewPatchMessageReqBuilder().\n\t\tMessageId(msgID).\n\t\tBody(larkim.NewPatchMessageReqBodyBuilder().\n\t\t\tContent(cardJSON).\n\t\t\tBuild()).\n\t\tBuild()\n\treturn p.withTransientRetry(ctx, \"refresh card\", func() error {\n\t\treturn p.withFreshTenantAccessTokenRetry(ctx, \"refresh card\", func(client *lark.Client, options ...larkcore.RequestOptionFunc) error {\n\t\t\tresp, err := client.Im.Message.Patch(ctx, req, options...)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"%s: refresh card: %w\", p.tag(), err)\n\t\t\t}\n\t\t\tif !resp.Success() {\n\t\t\t\treturn fmt.Errorf(\"%s: refresh card code=%d msg=%s\", p.tag(), resp.Code, resp.Msg)\n\t\t\t}\n\t\t\treturn nil\n\t\t})\n\t})\n}\n\n// renderCardMap converts a core.Card into the Feishu Interactive Card map\n// using the v1 format. Used both for message API (via renderCard) and\n// callback responses (CardActionTriggerResponse).\nfunc renderCardMap(card *core.Card, sessionKey string) map[string]any {\n\tresult := map[string]any{\n\t\t\"config\": map[string]any{\n\t\t\t\"wide_screen_mode\": true,\n\t\t},\n\t}","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/feishu/card.go#L60-L96","documentation":"Wraps a transport-level error from the Lark SDK's Im.Message.Patch call, which is used by the Feishu platform to refresh (update) an already-sent interactive card. The original SDK error (network failure, auth, invalid message_id) is preserved via %w. It is retried transiently via withTransientRetry/withFreshTenantAccessTokenRetry before surfacing.","triggerScenarios":"Calling the card refresh path (progress/streaming card updates) when client.Im.Message.Patch returns err: network outage, expired/invalid tenant_access_token after retries, invalid message_id, or card schema rejected at transport level.","commonSituations":"Feishu API outage or rate limiting during long streaming sessions; message recalled/deleted so Patch target no longer exists; app credentials rotated mid-run causing token fetch failures.","solutions":["Check network connectivity to open.feishu.cn (or the configured domain) and retry the operation.","Verify app_id/app_secret are valid and the token refresh path works (run cc-connect doctor).","Confirm the message_id being patched still exists (not recalled or deleted).","Inspect the wrapped SDK error (%w chain) for the underlying Feishu error code."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"// caller\nif err := p.refreshCard(ctx, req); err != nil {\n    slog.Warn(\"feishu: card refresh failed; card may be stale\", \"err\", err)\n    // non-fatal: keep session running, stale card degrades gracefully\n}","preventionTips":["Treat card refresh failures as non-fatal and degrade to text updates.","Monitor Feishu API status and token refresh logs.","Don't patch recalled messages; track recall state first."],"tags":["feishu","lark-sdk","card-refresh","network"],"backgroundTag":"api-request-failed","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}