From 4ebe252716ee1e08ebc24a010d7daddc79a44955 Mon Sep 17 00:00:00 2001 From: Levi Date: Mon, 19 Jan 2026 17:47:13 +0800 Subject: [PATCH 1/2] feat: add error handling for flagged generation --- src/app/i18n/locales/en.json | 6 +++- src/app/i18n/locales/zh.json | 6 +++- .../-components/chat/GenerationErrorItem.tsx | 16 ++++++++++ src/server/ai/provider/cloudflare.ts | 32 ++++++++++++------- src/server/db/schemas/chat.ts | 11 ++++++- src/server/lib/types.ts | 10 ++++++ 6 files changed, 66 insertions(+), 15 deletions(-) diff --git a/src/app/i18n/locales/en.json b/src/app/i18n/locales/en.json index d383bf4..ba4379b 100644 --- a/src/app/i18n/locales/en.json +++ b/src/app/i18n/locales/en.json @@ -69,6 +69,10 @@ "timeoutErrorDesc": "The request took too long, please try again", "tooManyRequests": "Too many requests", "tooManyRequestsDesc": "You have made too many requests, please try again later", + "promptFlagged": "Prompt flagged", + "promptFlaggedDesc": "Your prompt violates content policy, please modify and try again", + "inputImageFlagged": "Image flagged", + "inputImageFlaggedDesc": "Your image violates content policy, please change and try again", "unknownError": "Unknown error", "unknownErrorDesc": "An unexpected error occurred, please try again", "goToSettings": "Go to Settings", @@ -347,4 +351,4 @@ } } } -} +} \ No newline at end of file diff --git a/src/app/i18n/locales/zh.json b/src/app/i18n/locales/zh.json index 6cbe645..ebf5761 100644 --- a/src/app/i18n/locales/zh.json +++ b/src/app/i18n/locales/zh.json @@ -69,6 +69,10 @@ "timeoutErrorDesc": "请求时间过长,请重试", "tooManyRequests": "请求过于频繁", "tooManyRequestsDesc": "您的请求次数过多,请稍后再试", + "promptFlagged": "提示词违规", + "promptFlaggedDesc": "提示词违反内容政策,请修改后重试", + "inputImageFlagged": "图片违规", + "inputImageFlaggedDesc": "图片违反内容政策,请更换后重试", "unknownError": "未知错误", "unknownErrorDesc": "发生了意外错误,请重试", "goToSettings": "前往设置", @@ -347,4 +351,4 @@ } } } -} +} \ No newline at end of file diff --git a/src/app/routes/chat/-components/chat/GenerationErrorItem.tsx b/src/app/routes/chat/-components/chat/GenerationErrorItem.tsx index 26e1e77..6ad13ca 100644 --- a/src/app/routes/chat/-components/chat/GenerationErrorItem.tsx +++ b/src/app/routes/chat/-components/chat/GenerationErrorItem.tsx @@ -53,6 +53,22 @@ export function GenerationErrorItem({ errorReason, provider, onRetry, className buttonIcon: RefreshCw, buttonAction: "retry" as const, }; + case "PROMPT_FLAGGED": + return { + title: t("chat.generation.promptFlagged"), + description: t("chat.generation.promptFlaggedDesc"), + buttonText: t("chat.generation.retry"), + buttonIcon: RefreshCw, + buttonAction: "retry" as const, + }; + case "INPUT_IMAGE_FLAGGED": + return { + title: t("chat.generation.inputImageFlagged"), + description: t("chat.generation.inputImageFlaggedDesc"), + buttonText: t("chat.generation.retry"), + buttonIcon: RefreshCw, + buttonAction: "retry" as const, + }; default: return { title: t("chat.generation.unknownError"), diff --git a/src/server/ai/provider/cloudflare.ts b/src/server/ai/provider/cloudflare.ts index 99a1c48..c554575 100644 --- a/src/server/ai/provider/cloudflare.ts +++ b/src/server/ai/provider/cloudflare.ts @@ -1,5 +1,5 @@ import { inCfWorker } from "@/server/lib/env"; -import type { ReplacePropertyType } from "@/server/lib/types"; +import { GenError, type ReplacePropertyType } from "@/server/lib/types"; import { base64ToBlob, base64ToDataURI, dataURItoBase64, readableStreamToDataURI } from "@/server/lib/util"; import { getContext } from "@/server/service/context"; import { type TypixGenerateRequest, commonAspectRatioSizes } from "../types/api"; @@ -38,13 +38,27 @@ const createFormData = (params: any, model: CloudflareAiModel, request: TypixGen // Helper function to handle API response const handleApiResponse = async (resp: Response): Promise => { if (!resp.ok) { + const errorText = await resp.text(); if (resp.status === 401 || resp.status === 404) { - throw new Error("CONFIG_ERROR"); + throw new GenError("CONFIG_ERROR"); } if (resp.status === 429) { - throw new Error("TOO_MANY_REQUESTS"); + throw new GenError("TOO_MANY_REQUESTS"); + } + if (resp.status === 400) { + const errorResp = JSON.parse(errorText); + if (errorResp.errors && Array.isArray(errorResp.errors)) { + const firstErr = errorResp.errors.find((err: any) => err.code === 3030); + if (firstErr) { + if (firstErr.message.includes("prompt")) { + throw new GenError("PROMPT_FLAGGED"); + } + if (firstErr.message.includes("Input image")) { + throw new GenError("INPUT_IMAGE_FLAGGED"); + } + } + } } - const errorText = await resp.text(); throw new Error(`Cloudflare API error: ${resp.status} ${resp.statusText} - ${errorText}`); } @@ -249,15 +263,9 @@ const Cloudflare: CloudflareProvider = { images: allImages, }; } catch (error: any) { - if (error.message === "CONFIG_ERROR") { - return { - errorReason: "CONFIG_ERROR", - images: [], - }; - } - if (error.message === "TOO_MANY_REQUESTS") { + if (error instanceof GenError) { return { - errorReason: "TOO_MANY_REQUESTS", + errorReason: error.reason, images: [], }; } diff --git a/src/server/db/schemas/chat.ts b/src/server/db/schemas/chat.ts index 5de3dad..856c85c 100644 --- a/src/server/db/schemas/chat.ts +++ b/src/server/db/schemas/chat.ts @@ -49,7 +49,16 @@ export const messageAttachments = sqliteTable("message_attachments", { ...metaFields, }); -const errorReason = ["CONFIG_INVALID", "CONFIG_ERROR", "API_ERROR", "TOO_MANY_REQUESTS", "TIMEOUT", "UNKNOWN"] as const; +const errorReason = [ + "CONFIG_INVALID", + "CONFIG_ERROR", + "API_ERROR", + "TOO_MANY_REQUESTS", + "TIMEOUT", + "PROMPT_FLAGGED", + "INPUT_IMAGE_FLAGGED", + "UNKNOWN", +] as const; export type ErrorReason = (typeof errorReason)[number]; // Generations table - stores AI generation requests and results (images, videos, etc.) diff --git a/src/server/lib/types.ts b/src/server/lib/types.ts index 36f1fbb..776405b 100644 --- a/src/server/lib/types.ts +++ b/src/server/lib/types.ts @@ -1,4 +1,14 @@ +import type { ErrorReason } from "../db/schemas"; + export type StrictOmit = Omit; export type ReplacePropertyType = { [P in keyof T]: P extends K ? NewType : T[P]; }; +export class GenError extends Error { + reason: ErrorReason; + + constructor(reason: ErrorReason) { + super(reason); + this.reason = reason; + } +} From 8f0362cd1cacd740673b38148701133189295a8f Mon Sep 17 00:00:00 2001 From: Levi Date: Mon, 19 Jan 2026 17:49:02 +0800 Subject: [PATCH 2/2] fmt --- src/app/i18n/locales/en.json | 2 +- src/app/i18n/locales/zh.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/i18n/locales/en.json b/src/app/i18n/locales/en.json index ba4379b..e124ba4 100644 --- a/src/app/i18n/locales/en.json +++ b/src/app/i18n/locales/en.json @@ -351,4 +351,4 @@ } } } -} \ No newline at end of file +} diff --git a/src/app/i18n/locales/zh.json b/src/app/i18n/locales/zh.json index ebf5761..b3cc002 100644 --- a/src/app/i18n/locales/zh.json +++ b/src/app/i18n/locales/zh.json @@ -351,4 +351,4 @@ } } } -} \ No newline at end of file +}