{"record":{"id":"737c2c8896b514f6","repo":"zeroclaw-labs/zeroclaw","slug":"upload-file-failed-after-token-refresh-status-re","errorCode":null,"errorMessage":"upload file failed after token refresh: status={retry_status}, body={retry_response}","messagePattern":"upload file failed after token refresh: status=(.+?), body=(.+?)","errorType":"http","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-channels/src/lark.rs","lineNumber":2257,"sourceCode":"    }\n\n    async fn upload_lark_file(\n        &self,\n        token: &mut String,\n        marker: &LarkResolvedMediaMarker,\n        file_type: &'static str,\n    ) -> anyhow::Result<String> {\n        let url = format!(\"{}/im/v1/files\", self.api_base());\n        let form = build_lark_file_upload_form(marker, file_type).await?;\n        let (status, response) = self.post_multipart_once(&url, token, form).await?;\n        let response = if should_refresh_lark_tenant_token(status, &response) {\n            self.invalidate_token().await;\n            *token = self.get_tenant_access_token().await?;\n            let retry_form = build_lark_file_upload_form(marker, file_type).await?;\n            let (retry_status, retry_response) =\n                self.post_multipart_once(&url, token, retry_form).await?;\n            if should_refresh_lark_tenant_token(retry_status, &retry_response) {\n                anyhow::bail!(\n                    \"upload file failed after token refresh: status={retry_status}, body={retry_response}\"\n                );\n            }\n            ensure_lark_send_success(retry_status, &retry_response, \"upload file\")?;\n            retry_response\n        } else {\n            ensure_lark_send_success(status, &response, \"upload file\")?;\n            response\n        };\n\n        response\n            .pointer(\"/data/file_key\")\n            .or_else(|| response.get(\"file_key\"))\n            .and_then(|v| v.as_str())\n            .map(str::to_string)\n            .ok_or_else(|| anyhow::Error::msg(\"Lark/Feishu file upload returned no file_key\"))\n    }\n","sourceCodeStart":2239,"sourceCodeEnd":2275,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-channels/src/lark.rs#L2239-L2275","documentation":"The file upload path (build_lark_file_upload_form with a file_type such as opus/mp4/pdf) hit a refresh-indicating response, refreshed the tenant token, rebuilt the multipart form, retried — and the retry still looked like an invalid-token response. Same defect class as errors 108/109 but for generic file uploads. Retry status and body are included.","triggerScenarios":"Rotated app_secret or region-mismatched api_base, or the app missing the file-upload scope so the retry with a fresh token is still rejected.","commonSituations":"Credential rotation while running, duplicated channel processes, missing/withdrawn file upload permission after a permission audit.","solutions":["Verify app_id/app_secret and restart (see error 108).","Confirm the file upload scope for the relevant file_type is granted and the app version is published.","Inspect the retry body code: non-99991663 codes indicate permission or payload issues, not tokens.","Escalate to backoff-and-cooldown instead of immediate retry."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":"fn is_repeat_stale_token(err: &anyhow::Error) -> bool {\n    err.to_string().contains(\"upload file failed after token refresh\")\n}","tryCatchPattern":"if is_repeat_stale_token(&e) {\n    cooldown(Duration::from_secs(60)).await;\n    return lark.send(msg).await;\n}","preventionTips":["Defer file sends behind a retry queue with cooldown; files tolerate latency better than replies.","Confirm file-upload scopes per file_type after permission changes.","Fall back to a text description of the file when upload keeps failing."],"tags":["lark","file-upload","token-refresh","authentication","multipart"],"backgroundTag":"stale-access-token","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}