babalae/better-genshin-impact · error · NotifierException
Feishu upload image not found image key
Error message
Feishu upload image not found image key
What it means
Thrown by FeishuNotifier.UploadImage after a successful (2xx) HTTP POST to the Feishu image-upload endpoint (https://open.feishu.cn/open-apis/im/v1/images) when the parsed JSON body does not contain a non-empty data.image_key. The library treats a missing/null/empty image_key as a hard failure because the subsequent 'post' message (tag=img) needs that key to reference the uploaded asset.
Source
Thrown at BetterGenshinImpact/Service/Notifier/FeishuNotifier.cs:190
throw new NotifierException($"Feishu upload image failed with code: {uploadImageResponse.StatusCode}");
}
using (JsonDocument doc = JsonDocument.Parse(uploadResponseString))
{
JsonElement root = doc.RootElement;
if (root.TryGetProperty("data", out JsonElement dataElement) &&
dataElement.TryGetProperty("image_key", out JsonElement imageKeyElement))
{
var keyNullable = imageKeyElement.GetString();
if (keyNullable != null)
{
imageKey = keyNullable;
}
}
}
}
if (string.IsNullOrEmpty(imageKey))
{
throw new NotifierException($"Feishu upload image not found image key");
}
return imageKey;
}
}
View on GitHub (pinned to a7cb36712d)
Solutions
- Capture and log uploadResponseString before the throw to see the actual Feishu error code/message (e.g. code 99991663 permission denied).
- Confirm the Feishu app has the im:resource (im:message:send_as_image) permission and is published/approved in the developer console.
- Verify AppId/AppSecret are correct and that GetAccessToken returns a tenant_access_token for the same app used for upload.
- If the response shape changed, harden the parser to read data.code / data.msg and surface them in the exception instead of a generic 'not found image key'.
Example fix
// before
if (string.IsNullOrEmpty(imageKey))
{
throw new NotifierException($"Feishu upload image not found image key");
}
// after
var code = root.TryGetProperty("code", out var c) ? c.GetInt32() : -1;
var msg = root.TryGetProperty("msg", out var m) ? m.GetString() : uploadResponseString;
if (string.IsNullOrEmpty(imageKey))
{
throw new NotifierException($"Feishu upload image returned no image_key (code={code}, msg={msg})");
} Defensive patterns
Strategy: try-catch
Validate before calling
// Before enabling the Feishu image path, sanity-check the app credentials are present.
if (notificationData.Screenshot != null
&& (string.IsNullOrEmpty(notifier.AppId) || string.IsNullOrEmpty(notifier.AppSecret)))
{
// skip image upload, fall back to text-only — or warn the user.
} Type guard
// Ensure the credentials look like Feishu app credentials before sending.
static bool HasFeishuAppCredentials(FeishuNotifier n)
=> !string.IsNullOrEmpty(n.AppId) && !string.IsNullOrEmpty(n.AppSecret)
&& n.AppId.StartsWith("cli_"); Try / catch
try { await feishuNotifier.SendAsync(data); }
catch (NotifierException ex) when (ex.Message.Contains("image key"))
{
// degrade to text-only and retry once
data.Screenshot = null;
await feishuNotifier.SendAsync(data);
} Prevention
- Publish and approve the Feishu app with im:resource permission before enabling image notifications.
- Log the raw Feishu response body when parsing fails so the real error code surfaces.
- Fall back to text-only when image upload fails rather than dropping the whole notification.
When it happens
Trigger: uploadImageResponse.IsSuccessStatusCode is true, JsonDocument.Parse succeeds, but root.TryGetProperty("data", ...) or data.TryGetProperty("image_key", ...) returns false, OR imageKeyElement.GetString() returns null, leaving imageKey empty and triggering the line-188 IsNullOrEmpty guard.
Common situations: Feishu app lacks the im:resource permission scope; the access token is valid but the app is not approved/published so the upload silently returns code!=0 with no data node; the PNG payload exceeds Feishu size limits and the API returns a 200 with an error body; AppId/AppSecret mismatch produces a token with no upload rights; API contract drift after a Feishu OpenAPI version bump.
Related errors
- MeoW 昵称为空
- OneBot endpoint is not set
- OneBot requires either a user ID or group ID
- ServerChan SendKey为空
- Invalid key format for sctp.
AI-assisted analysis of babalae/better-genshin-impact@a7cb36712d (2026-08-13).
Data as JSON: /api/errors/13059a32e71545f2.
Report an issue: GitHub.