chenhg5/cc-connect · error
qqbot: upload rich media: empty file_info
Error message
qqbot: upload rich media: empty file_info
What it means
After a successful apiRequestJSON call, uploadRichMedia validates that the QQ rich-media API actually returned a non-empty file_info token, which is required to attach the media to a message. An empty file_info means the API responded 2xx but without the expected payload — the upload did not really complete, so the adapter treats it as an error.
Source
Thrown at platform/qqbot/qqbot.go:298
b64 := base64.StdEncoding.EncodeToString(data)
reqBody := map[string]any{
"file_type": fileType,
"file_data": b64,
"srv_send_msg": false,
}
if fileType == 4 && fileName != "" {
reqBody["file_name"] = fileName
}
var result struct {
FileInfo string `json:"file_info"`
}
if err := p.apiRequestJSON("POST", url, reqBody, &result); err != nil {
return "", err
}
if result.FileInfo == "" {
return "", fmt.Errorf("qqbot: upload rich media: empty file_info")
}
return result.FileInfo, nil
}
// apiRequestJSON is like apiRequest but also decodes the response body into result.
func (p *Platform) apiRequestJSON(method, url string, body any, result any) error {
var bodyReader io.Reader
if body != nil {
data, err := json.Marshal(body)
if err != nil {
return fmt.Errorf("qqbot: marshal body: %w", err)
}
bodyReader = bytes.NewReader(data)
}
token, err := p.getAccessToken()
if err != nil {
return fmt.Errorf("qqbot: get token: %w", err)View on GitHub (pinned to 4000b2338a)
Solutions
- Retry the upload — the condition is often transient on QQ's media service.
- Log the full raw response body (add temporary logging in apiRequestJSON) to see what was actually returned.
- Verify the file_type (1=image, 4=file) and payload size match QQ Bot rich-media API requirements.
- Check for a QQ Open Platform changelog entry about the rich-media response format.
- Confirm the bot's permissions for the target group/c2c media upload.
Example fix
// before
fileInfo, err := p.uploadRichMedia(rctx, 1, img.Data, "")
if err != nil { return err }
// after
var fileInfo string
for i := 0; i < 2; i++ {
fileInfo, err = p.uploadRichMedia(rctx, 1, img.Data, "")
if err == nil { break }
if !strings.Contains(err.Error(), "empty file_info") { break }
time.Sleep(time.Second)
}
if err != nil { return err } Defensive patterns
Strategy: retry
Validate before calling
// Validate payload before upload so the API cannot fail softly
if len(data) == 0 { return errors.New("qqbot: empty upload payload") } Try / catch
fileInfo, err := p.uploadRichMedia(rctx, fileType, data, name)
if err != nil {
if strings.Contains(err.Error(), "empty file_info") {
// transient/soft API failure: retry once, then log raw body
}
} Prevention
- Log the raw API response body on empty file_info to spot format drift early.
- Retry uploads once with backoff — QQ media service degrades intermittently.
- Subscribe to QQ Open Platform changelog for response-shape changes.
- Test the uploader against a stub server returning 200 with an empty body.
When it happens
Trigger: The rich-media endpoint returns HTTP 200 with a body lacking file_info (e.g. an error object in disguise, an async-processing response, or an API behavior change).
Common situations: QQ API version drift changing the response shape; uploading a file type the bot lacks permission for, with the API failing softly; intermittent media-service degradation returning empty bodies.
Understand the failure class
Background: "empty response", "returned no data", "empty embeddings": what HTTP 200-with-empty-body errors mean across libraries — this error's family across 36 libraries.
Related errors
- qqbot: upload file: %w
- empty downloadUrl in response
- empty accessToken in response
- qqbot: upload image: %w
- qqbot: api %s %s returned %d (after retry): %s
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/4165249c29eb2acc.
Report an issue: GitHub.