{"record":{"id":"240e450c18c8d3ee","repo":"chenhg5/cc-connect","slug":"s-stream-rich-card-text-w","errorCode":null,"errorMessage":"%s: stream rich card text: %w","messagePattern":"(.+?): stream rich card text: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"platform/feishu/feishu.go","lineNumber":5236,"sourceCode":"\tif h.cardID == \"\" {\n\t\treturn core.ErrNotSupported\n\t}\n\n\th.sequence++\n\tapiPath := fmt.Sprintf(\"/open-apis/cardkit/v1/cards/%s/elements/%s/content\",\n\t\th.cardID, richCardMainTextElementID)\n\tbody := map[string]any{\n\t\t\"content\":  fullText,\n\t\t\"sequence\": h.sequence,\n\t}\n\n\tvar apiResp *larkcore.ApiResp\n\tif err := p.withFreshTenantAccessTokenRetry(ctx, \"stream rich card text\", func(client *lark.Client, options ...larkcore.RequestOptionFunc) error {\n\t\tvar err error\n\t\tapiResp, err = client.Put(ctx, apiPath, body, larkcore.AccessTokenTypeTenant, options...)\n\t\treturn err\n\t}); err != nil {\n\t\treturn fmt.Errorf(\"%s: stream rich card text: %w\", p.tag(), err)\n\t}\n\tif apiResp == nil || apiResp.StatusCode != http.StatusOK {\n\t\treturn fmt.Errorf(\"%s: stream rich card text: HTTP status %d\", p.tag(), apiResp.StatusCode)\n\t}\n\tvar resp struct {\n\t\tCode int    `json:\"code\"`\n\t\tMsg  string `json:\"msg\"`\n\t}\n\tif err := json.Unmarshal(apiResp.RawBody, &resp); err != nil {\n\t\treturn fmt.Errorf(\"%s: stream rich card text: parse response: %w\", p.tag(), err)\n\t}\n\tif resp.Code != 0 {\n\t\terr := classifyFeishuCardAPIError(\"stream rich card text\", resp.Code, resp.Msg)\n\t\tif errors.Is(err, errFeishuCardRateLimited) {\n\t\t\tslog.Debug(p.tag()+\": stream rich card text rate limited; skipping frame\", \"code\", resp.Code)\n\t\t\treturn nil\n\t\t}\n\t\treturn fmt.Errorf(\"%s: %w\", p.tag(), err)","sourceCodeStart":5218,"sourceCodeEnd":5254,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/feishu/feishu.go#L5218-L5254","documentation":"Wraps a transport/client error from withFreshTenantAccessTokenRetry around the PUT /open-apis/cardkit/v1/cards/{card_id}/elements/{element_id}/content streaming-update call. Any network, token, or context failure during a streaming frame lands here, wrapped with %w so the original cause is preserved.","triggerScenarios":"client.Put returns an error: network interruption mid-stream, tenant token refresh failure, context deadline exceeded (streaming frame took too long), or the card was deleted making the request fail at transport/auth level.","commonSituations":"Flaky network between the host and Feishu during typewriter streaming; very long agent turns exceeding the frame ctx deadline; app credentials rotated mid-session so fresh-token acquisition fails; Feishu-side incidents.","solutions":["Inspect the wrapped inner error to identify network vs auth vs timeout","Since this is a streaming frame, treat as best-effort: log and let the next frame or the final full-card Patch converge the content","Verify token/credentials if the error persists across frames","Increase frame timeout or add small backoff between frames on transient failures"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"if h.cardID == \"\" {\n\treturn core.ErrNotSupported // don't attempt streaming without an entity\n}\nif err := ctx.Err(); err != nil { return err }","typeGuard":null,"tryCatchPattern":"if err := p.StreamRichCardText(ctx, h, text); err != nil {\n\tslog.Debug(\"stream frame failed; will converge on final patch\", \"err\", err)\n\t// frames are incremental: skip and continue\n}","preventionTips":["Treat individual frames as best-effort; the final UpdateMessage Patch carries full text","Use per-frame timeouts rather than one long deadline","Add small backoff after consecutive transport failures","Keep the final full-card Patch path always enabled"],"tags":["feishu","cardkit","network","streaming"],"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"}