sipeed/picoclaw · error
feishu image upload api error (code=%d msg=%s)
Error message
feishu image upload api error (code=%d msg=%s)
What it means
Feishu's image upload endpoint answered HTTP-level success semantics but with a non-zero business code (uploadResp.Success() false). The channel clears the cached tenant token when the code is 99991663. Typical codes: 230002 invalid image (unsupported format or >10MB), 99991663 invalid token, 99991400 rate limited.
Source
Thrown at pkg/channels/feishu/feishu_64.go:1153
}
// sendImage uploads an image and sends it as a message.
func (c *FeishuChannel) sendImage(ctx context.Context, chatID string, file *os.File) error {
// Upload image to get image_key
uploadReq := larkim.NewCreateImageReqBuilder().
Body(larkim.NewCreateImageReqBodyBuilder().
ImageType("message").
Image(file).
Build()).
Build()
uploadResp, err := c.client.Im.V1.Image.Create(ctx, uploadReq)
if err != nil {
return fmt.Errorf("feishu image upload: %w", err)
}
if !uploadResp.Success() {
c.invalidateTokenOnAuthError(uploadResp.Code)
return fmt.Errorf("feishu image upload api error (code=%d msg=%s)", uploadResp.Code, uploadResp.Msg)
}
if uploadResp.Data == nil || uploadResp.Data.ImageKey == nil {
return fmt.Errorf("feishu image upload: no image_key returned")
}
imageKey := *uploadResp.Data.ImageKey
// Send image message
content, _ := json.Marshal(map[string]string{"image_key": imageKey})
req := larkim.NewCreateMessageReqBuilder().
ReceiveIdType(larkim.CreateMessageV1ReceiveIDTypeChatId).
Body(larkim.NewCreateMessageReqBodyBuilder().
ReceiveId(chatID).
MsgType(larkim.MsgTypeImage).
Content(string(content)).
Build()).
Build()
View on GitHub (pinned to 49183d7e8d)
Solutions
- Match the code: 230002 -> convert to JPG/PNG and compress under 10MB; 99991663 -> fix credentials (cache is auto-cleared); 99991400 -> throttle uploads.
- Pre-validate size and MIME type before sending (see exampleFix).
- Grant im:image permission to the app in the Feishu console.
- If the file came from user upload, re-encode server-side instead of forwarding raw bytes.
Example fix
// before — any file goes straight to the API, 230002 surfaces after the upload
err := ch.SendMedia(ctx, msg)
// after — validate before uploading
if fi, serr := f.Stat(); serr == nil && fi.Size() > 10<<20 {
return fmt.Errorf("image %s is %d bytes; Feishu limit is 10MB", name, fi.Size())
}
if mt := mime.TypeByExtension(filepath.Ext(name)); mt != "image/jpeg" && mt != "image/png" {
return fmt.Errorf("image %s is %s; convert to JPEG/PNG first", name, mt)
} Defensive patterns
Strategy: validation
Validate before calling
const feishuMaxImage = 10 << 20
if fi, serr := f.Stat(); serr != nil || fi.Size() > feishuMaxImage {
return fmt.Errorf("image exceeds Feishu 10MB limit or is unreadable")
}
switch mime.TypeByExtension(filepath.Ext(name)) {
case "image/jpeg", "image/png":
default:
return fmt.Errorf("image %s must be JPEG or PNG", name)
} Type guard
func isFeishuUploadAPIErr(err error) bool {
return strings.Contains(err.Error(), "feishu image upload api error (code=")
} Try / catch
if err := ch.SendMedia(ctx, msg); err != nil {
if strings.Contains(err.Error(), "code=230002") {
// invalid image: convert/compress and retry — do not blind-retry the same bytes
}
if strings.Contains(err.Error(), "code=99991663") {
// token: credentials problem, cache already cleared by the channel
}
} Prevention
- Convert WebP/GIF/HEIC to JPEG/PNG before sending
- Compress images under 10MB server-side
- Grant im:image scope up front
- Throttle uploads to avoid 99991400
When it happens
Trigger: Im.V1.Image.Create with ImageType('message') returns code 230002: file is not JPG/PNG, exceeds 10MB, or is corrupted; 99991663 after credential rotation; 99991400 from burst uploads; app missing im:image scope.
Common situations: Sending WebP/GIF/HEIC which message-type images reject; phone-sourced photos over 10MB; bot token regenerated in the developer console but still cached.
Related errors
- feishu file upload api error (code=%d msg=%s)
- feishu image send api error (code=%d msg=%s)
- feishu file send api error (code=%d msg=%s)
- feishu api error (code=%d msg=%s): %w
- feishu text api error (code=%d msg=%s): %w
AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15).
Data as JSON: /api/errors/32072d4a08a1b36b.
Report an issue: GitHub.