{"record":{"id":"9d768b2626a27ff8","repo":"chenhg5/cc-connect","slug":"s-stream-rich-card-text-http-status-d","errorCode":null,"errorMessage":"%s: stream rich card text: HTTP status %d","messagePattern":"(.+?): stream rich card text: HTTP status (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"platform/feishu/feishu.go","lineNumber":5239,"sourceCode":"\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)\n\t}\n\treturn nil\n}","sourceCodeStart":5221,"sourceCodeEnd":5257,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/feishu/feishu.go#L5221-L5257","documentation":"The streaming PUT completed at transport level but returned a non-200 HTTP status (or nil response). Unlike business errors (code != 0), this catches 401 expired/invalid token, 403 missing Cardkit permission, 404 card or element not found, and 5xx server errors before the body is parsed.","triggerScenarios":"PUT element content returns 401 (bad tenant token), 403 (app lacks cardkit permission), 404 (card_id deleted/never existed — e.g. entity creation silently failed earlier), 429 throttle expressed at HTTP layer, or 5xx from Feishu.","commonSituations":"Card entity expired/deleted on Feishu's side mid-session; permission not released for the app; token refresh race; Feishu throttling a burst of streaming frames.","solutions":["Check the status: 404 → card_id stale, abandon streaming and fall back to full-card Patch; 401/403 → fix credentials/Cardkit permissions; 5xx/429 → retry the frame with backoff","Because frames are incremental, skipping a failed frame is usually safe — the final Patch carries the complete text","Confirm the card entity from createCardEntity still exists (they can expire)","Grant and release cardkit:card scope if 403"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"// check card entity exists before streaming\nif h.cardID == \"\" { return core.ErrNotSupported }","typeGuard":null,"tryCatchPattern":"if err := p.StreamRichCardText(ctx, h, text); err != nil {\n\tif strings.Contains(err.Error(), \"HTTP status 404\") {\n\t\t// card entity gone: stop streaming, rely on final Patch\n\t}\n}","preventionTips":["Don't stream against card entities older than their expiry","Grant and release Cardkit permissions to avoid 403","Pace frames below Feishu's element rate limits","Always finish a turn with the full-card Patch so content converges even if frames fail"],"tags":["feishu","cardkit","http","streaming"],"backgroundTag":"http-non-2xx-response","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"}