chenhg5/cc-connect · error
%s: upload audio: %w
Error message
%s: upload audio: %w
What it means
This wraps an SDK-level failure from client.Im.File.Create, the Feishu upload API used to push the audio file before it can be referenced by a voice message. The upload runs inside withFreshTenantAccessTokenRetry (inside transient retry), so seeing this error means the upload failed even after retries with a freshly issued tenant_access_token.
Source
Thrown at platform/feishu/feishu.go:5492
}
audio = converted
format = "opus"
}
var uploadResp *larkim.CreateFileResp
if err := p.withTransientRetry(ctx, "upload audio", func() error {
return p.withFreshTenantAccessTokenRetry(ctx, "upload audio", func(client *lark.Client, options ...larkcore.RequestOptionFunc) error {
req := larkim.NewCreateFileReqBuilder().
Body(larkim.NewCreateFileReqBodyBuilder().
FileType(larkim.FileTypeOpus).
FileName("tts_audio.opus").
File(bytes.NewReader(audio)).
Build()).
Build()
var err error
uploadResp, err = client.Im.File.Create(ctx, req, options...)
if err != nil {
return fmt.Errorf("%s: upload audio: %w", p.tag(), err)
}
if !uploadResp.Success() {
return fmt.Errorf("%s: upload audio code=%d msg=%s", p.tag(), uploadResp.Code, uploadResp.Msg)
}
return nil
})
}); err != nil {
return err
}
if uploadResp.Data == nil || uploadResp.Data.FileKey == nil {
return fmt.Errorf("%s: upload audio: no file_key returned", p.tag())
}
fileKey := *uploadResp.Data.FileKey
slog.Debug(p.tag()+": audio uploaded", "file_key", fileKey, "format", format, "size", len(audio))
audioMsg := larkim.MessageAudio{FileKey: fileKey}
audioContent, err := audioMsg.String()View on GitHub (pinned to 4000b2338a)
Solutions
- Inspect the unwrapped cause to distinguish network vs auth vs cancellation
- Verify tenant_access_token acquisition works (check app_id/app_secret)
- Retry later — transient-retry already ran, so the failure is likely persistent
- Reduce audio size/duration to shrink the upload
Example fix
err := p.SendAudio(ctx, rc, audio, "opus")
if err != nil {
slog.Error("feishu audio upload failed after retries", "err", err)
// fall back to sending a text notice instead
p.Reply(ctx, rc, "(voice message failed to upload)")
} Defensive patterns
Strategy: retry
Validate before calling
// pre-check token acquisition
// ensure ctx has sufficient deadline for large uploads
if d, ok := ctx.Deadline(); ok && time.Until(d) < 30*time.Second { /* extend deadline */ } Try / catch
err := p.SendAudio(ctx, rc, audio, "opus")
if err != nil {
if errors.Is(err, context.Canceled) { return err } // don't retry cancellations
time.Sleep(backoff); err = p.SendAudio(ctx, rc, audio, "opus")
} Prevention
- Size audio within Feishu upload limits
- Ensure stable connectivity to open.feishu.cn
- Keep app_id/app_secret valid so fresh-token retries succeed
- Bound retry attempts with exponential backoff
When it happens
Trigger: client.Im.File.Create returns a non-nil err after retries: network failure, token acquisition failure, ctx cancellation mid-upload (large files on slow links), or multipart request build failure.
Common situations: Large audio files timing out on constrained networks; Feishu open platform outage; app credentials revoked so fresh token fetch fails inside the retry wrapper; proxy blocking multipart uploads.
Understand the failure class
Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.
Related errors
- %s: upload image: %w
- %s: upload file: %w
- %s: upload audio: no file_key returned
- %s: upload video: %w
- redirected to unsupported image URL
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/fe8e03728f1cf1ca.
Report an issue: GitHub.