{"record":{"id":"cf79404b9ff19a8f","repo":"Tencent/WeKnora","slug":"no-file-key-url-or-media-id-in-message","errorCode":null,"errorMessage":"no file key (URL or media_id) in message","messagePattern":"no file key \\(URL or media_id\\) in message","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/im/wecom/webhook_adapter.go","lineNumber":539,"sourceCode":"\tPicUrl       string   `xml:\"PicUrl\"`       // image: download URL\n\tMediaId      string   `xml:\"MediaId\"`      // image/voice/video: media ID for download\n\tFormat       string   `xml:\"Format\"`       // voice: audio format (amr/speex)\n\tThumbMediaId string   `xml:\"ThumbMediaId\"` // video: thumbnail media ID\n\tMsgID        string   `xml:\"MsgId\"`\n\tAgentID      string   `xml:\"AgentID\"`\n\tChatID       string   `xml:\"ChatId\"`\n}\n\n// ──────────────────────────────────────────────────────────────────────\n// File download support for WeCom webhook mode\n// ──────────────────────────────────────────────────────────────────────\n\n// DownloadFile downloads a file/image from WeCom.\n// For webhook mode, images come with MediaId (temporary media) which can be\n// downloaded via the GetMedia API, or PicUrl for direct download.\nfunc (a *WebhookAdapter) DownloadFile(ctx context.Context, msg *im.IncomingMessage) (io.ReadCloser, string, error) {\n\tif msg.FileKey == \"\" {\n\t\treturn nil, \"\", fmt.Errorf(\"no file key (URL or media_id) in message\")\n\t}\n\n\tfileName := msg.FileName\n\tif fileName == \"\" {\n\t\tfileName = msg.FileKey\n\t}\n\n\t// If FileKey looks like a URL, download directly\n\tif strings.HasPrefix(msg.FileKey, \"http://\") || strings.HasPrefix(msg.FileKey, \"https://\") {\n\t\treturn downloadFromURL(ctx, msg.FileKey, fileName, a.extraAllowedHost)\n\t}\n\n\t// Otherwise treat as media_id, download via temporary media API\n\taccessToken, err := a.getAccessToken(ctx)\n\tif err != nil {\n\t\treturn nil, \"\", fmt.Errorf(\"get access token: %w\", err)\n\t}\n","sourceCodeStart":521,"sourceCodeEnd":557,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/im/wecom/webhook_adapter.go#L521-L557","documentation":"DownloadFile extracts the file reference from msg.FileKey (a PicUrl or MediaId). When the incoming WeCom message carries neither — FileKey is empty — there is nothing to download and the method returns this error. WeCom text and event messages legitimately contain no file, so callers must check before invoking.","triggerScenarios":"Calling DownloadFile on an IncomingMessage parsed from a text/event message (no PicUrl, no MediaId); a message type where the adapter failed to populate FileKey; forwarding messages that lost their media reference.","commonSituations":"Treating every incoming callback as having an attachment; upstream normalization not mapping PicUrl/MediaId into FileKey for a new message type; users sending stickers or non-image types the adapter doesn't map.","solutions":["Check msg.FileKey != \"\" (or msg type) before calling DownloadFile","Verify the adapter's ParseCallback/parse logic maps PicUrl and MediaId to FileKey for the message types you receive","Log msg type for messages hitting this path to confirm only genuinely file-less types reach it","Skip or handle differently messages of type text/event instead of attempting a download"],"exampleFix":"// before\nrc, name, err := adapter.DownloadFile(ctx, msg)\n// after\nif msg.FileKey == \"\" { return nil } // not a file message\nrc, name, err := adapter.DownloadFile(ctx, msg)","handlingStrategy":"validation","validationCode":"if msg.FileKey == \"\" { /* skip download — message has no attachment */ }","typeGuard":"func hasDownloadableFile(msg *im.IncomingMessage) bool { return msg.FileKey != \"\" }","tryCatchPattern":"if msg.FileKey == \"\" { return nil } // guard before call\nrc, name, err := adapter.DownloadFile(ctx, msg)\nif err != nil && strings.Contains(err.Error(), \"no file key\") {\n    logger.Debugf(\"message %s has no file\", msg.ID)\n    return nil\n}","preventionTips":["Check message type before attempting downloads","Ensure adapter parsing maps PicUrl/MediaId into FileKey for all supported message types","Cover each incoming message type with a parse test asserting FileKey presence"],"tags":["download","missing-field","wecom"],"backgroundTag":"missing-key-file","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}