From ec2dca3e2a5ad8890a1b699f64a1231a3b297291 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Tue, 7 Apr 2026 23:58:04 -0700 Subject: [PATCH 1/3] fix: address PR review comments on staging release - Add try/catch around clipboard.writeText() in CopyCodeButton - Add missing folder and past_chat cases in resolveResourceFromContext - Return 400 for ZodError instead of 500 in all 8 Athena API routes Co-Authored-By: Claude Opus 4.6 --- .../app/api/tools/athena/create-named-query/route.ts | 6 ++++++ .../app/api/tools/athena/get-named-query/route.ts | 6 ++++++ .../api/tools/athena/get-query-execution/route.ts | 6 ++++++ .../app/api/tools/athena/get-query-results/route.ts | 6 ++++++ .../app/api/tools/athena/list-named-queries/route.ts | 6 ++++++ .../api/tools/athena/list-query-executions/route.ts | 6 ++++++ apps/sim/app/api/tools/athena/start-query/route.ts | 6 ++++++ apps/sim/app/api/tools/athena/stop-query/route.ts | 6 ++++++ apps/sim/app/workspace/[workspaceId]/home/home.tsx | 4 ++++ apps/sim/components/ui/copy-code-button.tsx | 12 ++++++++---- 10 files changed, 60 insertions(+), 4 deletions(-) diff --git a/apps/sim/app/api/tools/athena/create-named-query/route.ts b/apps/sim/app/api/tools/athena/create-named-query/route.ts index f9f997d618..f49bc16247 100644 --- a/apps/sim/app/api/tools/athena/create-named-query/route.ts +++ b/apps/sim/app/api/tools/athena/create-named-query/route.ts @@ -55,6 +55,12 @@ export async function POST(request: NextRequest) { }, }) } catch (error) { + if (error instanceof z.ZodError) { + return NextResponse.json( + { error: error.errors[0]?.message ?? 'Invalid request' }, + { status: 400 } + ) + } const errorMessage = error instanceof Error ? error.message : 'Failed to create Athena named query' logger.error('CreateNamedQuery failed', { error: errorMessage }) diff --git a/apps/sim/app/api/tools/athena/get-named-query/route.ts b/apps/sim/app/api/tools/athena/get-named-query/route.ts index 83e9845b75..394bbda2b8 100644 --- a/apps/sim/app/api/tools/athena/get-named-query/route.ts +++ b/apps/sim/app/api/tools/athena/get-named-query/route.ts @@ -53,6 +53,12 @@ export async function POST(request: NextRequest) { }, }) } catch (error) { + if (error instanceof z.ZodError) { + return NextResponse.json( + { error: error.errors[0]?.message ?? 'Invalid request' }, + { status: 400 } + ) + } const errorMessage = error instanceof Error ? error.message : 'Failed to get Athena named query' logger.error('GetNamedQuery failed', { error: errorMessage }) return NextResponse.json({ error: errorMessage }, { status: 500 }) diff --git a/apps/sim/app/api/tools/athena/get-query-execution/route.ts b/apps/sim/app/api/tools/athena/get-query-execution/route.ts index b043db1141..129f4794dc 100644 --- a/apps/sim/app/api/tools/athena/get-query-execution/route.ts +++ b/apps/sim/app/api/tools/athena/get-query-execution/route.ts @@ -63,6 +63,12 @@ export async function POST(request: NextRequest) { }, }) } catch (error) { + if (error instanceof z.ZodError) { + return NextResponse.json( + { error: error.errors[0]?.message ?? 'Invalid request' }, + { status: 400 } + ) + } const errorMessage = error instanceof Error ? error.message : 'Failed to get Athena query execution' logger.error('GetQueryExecution failed', { error: errorMessage }) diff --git a/apps/sim/app/api/tools/athena/get-query-results/route.ts b/apps/sim/app/api/tools/athena/get-query-results/route.ts index d89488371d..260cc73dc0 100644 --- a/apps/sim/app/api/tools/athena/get-query-results/route.ts +++ b/apps/sim/app/api/tools/athena/get-query-results/route.ts @@ -74,6 +74,12 @@ export async function POST(request: NextRequest) { }, }) } catch (error) { + if (error instanceof z.ZodError) { + return NextResponse.json( + { error: error.errors[0]?.message ?? 'Invalid request' }, + { status: 400 } + ) + } const errorMessage = error instanceof Error ? error.message : 'Failed to get Athena query results' logger.error('GetQueryResults failed', { error: errorMessage }) diff --git a/apps/sim/app/api/tools/athena/list-named-queries/route.ts b/apps/sim/app/api/tools/athena/list-named-queries/route.ts index c9f74ca216..326e03711b 100644 --- a/apps/sim/app/api/tools/athena/list-named-queries/route.ts +++ b/apps/sim/app/api/tools/athena/list-named-queries/route.ts @@ -51,6 +51,12 @@ export async function POST(request: NextRequest) { }, }) } catch (error) { + if (error instanceof z.ZodError) { + return NextResponse.json( + { error: error.errors[0]?.message ?? 'Invalid request' }, + { status: 400 } + ) + } const errorMessage = error instanceof Error ? error.message : 'Failed to list Athena named queries' logger.error('ListNamedQueries failed', { error: errorMessage }) diff --git a/apps/sim/app/api/tools/athena/list-query-executions/route.ts b/apps/sim/app/api/tools/athena/list-query-executions/route.ts index 096afee99c..958d09b173 100644 --- a/apps/sim/app/api/tools/athena/list-query-executions/route.ts +++ b/apps/sim/app/api/tools/athena/list-query-executions/route.ts @@ -51,6 +51,12 @@ export async function POST(request: NextRequest) { }, }) } catch (error) { + if (error instanceof z.ZodError) { + return NextResponse.json( + { error: error.errors[0]?.message ?? 'Invalid request' }, + { status: 400 } + ) + } const errorMessage = error instanceof Error ? error.message : 'Failed to list Athena query executions' logger.error('ListQueryExecutions failed', { error: errorMessage }) diff --git a/apps/sim/app/api/tools/athena/start-query/route.ts b/apps/sim/app/api/tools/athena/start-query/route.ts index 6af793cbe0..0555246aa8 100644 --- a/apps/sim/app/api/tools/athena/start-query/route.ts +++ b/apps/sim/app/api/tools/athena/start-query/route.ts @@ -67,6 +67,12 @@ export async function POST(request: NextRequest) { }, }) } catch (error) { + if (error instanceof z.ZodError) { + return NextResponse.json( + { error: error.errors[0]?.message ?? 'Invalid request' }, + { status: 400 } + ) + } const errorMessage = error instanceof Error ? error.message : 'Failed to start Athena query' logger.error('StartQuery failed', { error: errorMessage }) return NextResponse.json({ error: errorMessage }, { status: 500 }) diff --git a/apps/sim/app/api/tools/athena/stop-query/route.ts b/apps/sim/app/api/tools/athena/stop-query/route.ts index 2f3422b36e..0a7558d314 100644 --- a/apps/sim/app/api/tools/athena/stop-query/route.ts +++ b/apps/sim/app/api/tools/athena/stop-query/route.ts @@ -43,6 +43,12 @@ export async function POST(request: NextRequest) { }, }) } catch (error) { + if (error instanceof z.ZodError) { + return NextResponse.json( + { error: error.errors[0]?.message ?? 'Invalid request' }, + { status: 400 } + ) + } const errorMessage = error instanceof Error ? error.message : 'Failed to stop Athena query' logger.error('StopQuery failed', { error: errorMessage }) return NextResponse.json({ error: errorMessage }, { status: 500 }) diff --git a/apps/sim/app/workspace/[workspaceId]/home/home.tsx b/apps/sim/app/workspace/[workspaceId]/home/home.tsx index 132d87b2a9..e79e307def 100644 --- a/apps/sim/app/workspace/[workspaceId]/home/home.tsx +++ b/apps/sim/app/workspace/[workspaceId]/home/home.tsx @@ -273,6 +273,10 @@ export function Home({ chatId }: HomeProps = {}) { return context.tableId ? { type: 'table', id: context.tableId } : null case 'file': return context.fileId ? { type: 'file', id: context.fileId } : null + case 'folder': + return context.folderId ? { type: 'folder', id: context.folderId } : null + case 'past_chat': + return context.chatId ? { type: 'task', id: context.chatId } : null default: return null } diff --git a/apps/sim/components/ui/copy-code-button.tsx b/apps/sim/components/ui/copy-code-button.tsx index 5113c79601..87f17764cf 100644 --- a/apps/sim/components/ui/copy-code-button.tsx +++ b/apps/sim/components/ui/copy-code-button.tsx @@ -14,10 +14,14 @@ export function CopyCodeButton({ code, className }: CopyCodeButtonProps) { const timerRef = useRef | null>(null) const handleCopy = useCallback(async () => { - await navigator.clipboard.writeText(code) - setCopied(true) - if (timerRef.current) clearTimeout(timerRef.current) - timerRef.current = setTimeout(() => setCopied(false), 2000) + try { + await navigator.clipboard.writeText(code) + setCopied(true) + if (timerRef.current) clearTimeout(timerRef.current) + timerRef.current = setTimeout(() => setCopied(false), 2000) + } catch { + // Clipboard write can fail when document lacks focus or permission is denied + } }, [code]) useEffect( From 912033fa96c37fe1c28f9f170a53b1499188da71 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Wed, 8 Apr 2026 00:00:59 -0700 Subject: [PATCH 2/3] fix(api): return 400 for Zod validation errors across 27 API routes Routes using z.parse() were returning 500 for ZodError (client input validation failures). Added instanceof z.ZodError check to return 400 before the generic 500 handler, matching the established pattern used by 115+ other routes. Affected services: CloudWatch (7), CloudFormation (7), DynamoDB (6), Slack (3), Outlook (2), OneDrive (1), Google Drive (1). Co-Authored-By: Claude Opus 4.6 --- .../describe-stack-drift-detection-status/route.ts | 6 ++++++ .../api/tools/cloudformation/describe-stack-events/route.ts | 6 ++++++ .../app/api/tools/cloudformation/describe-stacks/route.ts | 6 ++++++ .../api/tools/cloudformation/detect-stack-drift/route.ts | 6 ++++++ apps/sim/app/api/tools/cloudformation/get-template/route.ts | 6 ++++++ .../api/tools/cloudformation/list-stack-resources/route.ts | 6 ++++++ .../app/api/tools/cloudformation/validate-template/route.ts | 6 ++++++ apps/sim/app/api/tools/cloudwatch/describe-alarms/route.ts | 6 ++++++ .../app/api/tools/cloudwatch/describe-log-groups/route.ts | 6 ++++++ .../app/api/tools/cloudwatch/describe-log-streams/route.ts | 6 ++++++ apps/sim/app/api/tools/cloudwatch/get-log-events/route.ts | 6 ++++++ .../app/api/tools/cloudwatch/get-metric-statistics/route.ts | 6 ++++++ apps/sim/app/api/tools/cloudwatch/list-metrics/route.ts | 6 ++++++ apps/sim/app/api/tools/cloudwatch/query-logs/route.ts | 6 ++++++ apps/sim/app/api/tools/dynamodb/delete/route.ts | 6 ++++++ apps/sim/app/api/tools/dynamodb/get/route.ts | 6 ++++++ apps/sim/app/api/tools/dynamodb/put/route.ts | 6 ++++++ apps/sim/app/api/tools/dynamodb/query/route.ts | 6 ++++++ apps/sim/app/api/tools/dynamodb/scan/route.ts | 6 ++++++ apps/sim/app/api/tools/dynamodb/update/route.ts | 6 ++++++ apps/sim/app/api/tools/google_drive/download/route.ts | 6 ++++++ apps/sim/app/api/tools/onedrive/download/route.ts | 6 ++++++ apps/sim/app/api/tools/outlook/draft/route.ts | 6 ++++++ apps/sim/app/api/tools/outlook/send/route.ts | 6 ++++++ apps/sim/app/api/tools/slack/download/route.ts | 6 ++++++ apps/sim/app/api/tools/slack/send-ephemeral/route.ts | 6 ++++++ apps/sim/app/api/tools/slack/send-message/route.ts | 6 ++++++ 27 files changed, 162 insertions(+) diff --git a/apps/sim/app/api/tools/cloudformation/describe-stack-drift-detection-status/route.ts b/apps/sim/app/api/tools/cloudformation/describe-stack-drift-detection-status/route.ts index b47611b0cf..d267bb01fa 100644 --- a/apps/sim/app/api/tools/cloudformation/describe-stack-drift-detection-status/route.ts +++ b/apps/sim/app/api/tools/cloudformation/describe-stack-drift-detection-status/route.ts @@ -53,6 +53,12 @@ export async function POST(request: NextRequest) { }, }) } catch (error) { + if (error instanceof z.ZodError) { + return NextResponse.json( + { error: error.errors[0]?.message ?? 'Invalid request' }, + { status: 400 } + ) + } const errorMessage = error instanceof Error ? error.message : 'Failed to describe stack drift detection status' logger.error('DescribeStackDriftDetectionStatus failed', { error: errorMessage }) diff --git a/apps/sim/app/api/tools/cloudformation/describe-stack-events/route.ts b/apps/sim/app/api/tools/cloudformation/describe-stack-events/route.ts index b838512a43..a3108eebff 100644 --- a/apps/sim/app/api/tools/cloudformation/describe-stack-events/route.ts +++ b/apps/sim/app/api/tools/cloudformation/describe-stack-events/route.ts @@ -70,6 +70,12 @@ export async function POST(request: NextRequest) { output: { events }, }) } catch (error) { + if (error instanceof z.ZodError) { + return NextResponse.json( + { error: error.errors[0]?.message ?? 'Invalid request' }, + { status: 400 } + ) + } const errorMessage = error instanceof Error ? error.message : 'Failed to describe CloudFormation stack events' logger.error('DescribeStackEvents failed', { error: errorMessage }) diff --git a/apps/sim/app/api/tools/cloudformation/describe-stacks/route.ts b/apps/sim/app/api/tools/cloudformation/describe-stacks/route.ts index 30cf207d7e..d8fc946b51 100644 --- a/apps/sim/app/api/tools/cloudformation/describe-stacks/route.ts +++ b/apps/sim/app/api/tools/cloudformation/describe-stacks/route.ts @@ -78,6 +78,12 @@ export async function POST(request: NextRequest) { output: { stacks }, }) } catch (error) { + if (error instanceof z.ZodError) { + return NextResponse.json( + { error: error.errors[0]?.message ?? 'Invalid request' }, + { status: 400 } + ) + } const errorMessage = error instanceof Error ? error.message : 'Failed to describe CloudFormation stacks' logger.error('DescribeStacks failed', { error: errorMessage }) diff --git a/apps/sim/app/api/tools/cloudformation/detect-stack-drift/route.ts b/apps/sim/app/api/tools/cloudformation/detect-stack-drift/route.ts index 30d0516681..a21c3e7041 100644 --- a/apps/sim/app/api/tools/cloudformation/detect-stack-drift/route.ts +++ b/apps/sim/app/api/tools/cloudformation/detect-stack-drift/route.ts @@ -48,6 +48,12 @@ export async function POST(request: NextRequest) { }, }) } catch (error) { + if (error instanceof z.ZodError) { + return NextResponse.json( + { error: error.errors[0]?.message ?? 'Invalid request' }, + { status: 400 } + ) + } const errorMessage = error instanceof Error ? error.message : 'Failed to detect CloudFormation stack drift' logger.error('DetectStackDrift failed', { error: errorMessage }) diff --git a/apps/sim/app/api/tools/cloudformation/get-template/route.ts b/apps/sim/app/api/tools/cloudformation/get-template/route.ts index 9abdad4e17..a5e6edeeaa 100644 --- a/apps/sim/app/api/tools/cloudformation/get-template/route.ts +++ b/apps/sim/app/api/tools/cloudformation/get-template/route.ts @@ -45,6 +45,12 @@ export async function POST(request: NextRequest) { }, }) } catch (error) { + if (error instanceof z.ZodError) { + return NextResponse.json( + { error: error.errors[0]?.message ?? 'Invalid request' }, + { status: 400 } + ) + } const errorMessage = error instanceof Error ? error.message : 'Failed to get CloudFormation template' logger.error('GetTemplate failed', { error: errorMessage }) diff --git a/apps/sim/app/api/tools/cloudformation/list-stack-resources/route.ts b/apps/sim/app/api/tools/cloudformation/list-stack-resources/route.ts index ca22c8e856..dfc6517136 100644 --- a/apps/sim/app/api/tools/cloudformation/list-stack-resources/route.ts +++ b/apps/sim/app/api/tools/cloudformation/list-stack-resources/route.ts @@ -67,6 +67,12 @@ export async function POST(request: NextRequest) { output: { resources }, }) } catch (error) { + if (error instanceof z.ZodError) { + return NextResponse.json( + { error: error.errors[0]?.message ?? 'Invalid request' }, + { status: 400 } + ) + } const errorMessage = error instanceof Error ? error.message : 'Failed to list CloudFormation stack resources' logger.error('ListStackResources failed', { error: errorMessage }) diff --git a/apps/sim/app/api/tools/cloudformation/validate-template/route.ts b/apps/sim/app/api/tools/cloudformation/validate-template/route.ts index e2a8b4428e..1264d813fd 100644 --- a/apps/sim/app/api/tools/cloudformation/validate-template/route.ts +++ b/apps/sim/app/api/tools/cloudformation/validate-template/route.ts @@ -53,6 +53,12 @@ export async function POST(request: NextRequest) { }, }) } catch (error) { + if (error instanceof z.ZodError) { + return NextResponse.json( + { error: error.errors[0]?.message ?? 'Invalid request' }, + { status: 400 } + ) + } const errorMessage = error instanceof Error ? error.message : 'Failed to validate CloudFormation template' logger.error('ValidateTemplate failed', { error: errorMessage }) diff --git a/apps/sim/app/api/tools/cloudwatch/describe-alarms/route.ts b/apps/sim/app/api/tools/cloudwatch/describe-alarms/route.ts index 0ab6c4aad8..3fc65ab5bf 100644 --- a/apps/sim/app/api/tools/cloudwatch/describe-alarms/route.ts +++ b/apps/sim/app/api/tools/cloudwatch/describe-alarms/route.ts @@ -88,6 +88,12 @@ export async function POST(request: NextRequest) { output: { alarms: [...metricAlarms, ...compositeAlarms] }, }) } catch (error) { + if (error instanceof z.ZodError) { + return NextResponse.json( + { error: error.errors[0]?.message ?? 'Invalid request' }, + { status: 400 } + ) + } const errorMessage = error instanceof Error ? error.message : 'Failed to describe CloudWatch alarms' logger.error('DescribeAlarms failed', { error: errorMessage }) diff --git a/apps/sim/app/api/tools/cloudwatch/describe-log-groups/route.ts b/apps/sim/app/api/tools/cloudwatch/describe-log-groups/route.ts index a10f46c4ef..fcb29be528 100644 --- a/apps/sim/app/api/tools/cloudwatch/describe-log-groups/route.ts +++ b/apps/sim/app/api/tools/cloudwatch/describe-log-groups/route.ts @@ -54,6 +54,12 @@ export async function POST(request: NextRequest) { output: { logGroups }, }) } catch (error) { + if (error instanceof z.ZodError) { + return NextResponse.json( + { error: error.errors[0]?.message ?? 'Invalid request' }, + { status: 400 } + ) + } const errorMessage = error instanceof Error ? error.message : 'Failed to describe CloudWatch log groups' logger.error('DescribeLogGroups failed', { error: errorMessage }) diff --git a/apps/sim/app/api/tools/cloudwatch/describe-log-streams/route.ts b/apps/sim/app/api/tools/cloudwatch/describe-log-streams/route.ts index d74ad6de26..223e51617b 100644 --- a/apps/sim/app/api/tools/cloudwatch/describe-log-streams/route.ts +++ b/apps/sim/app/api/tools/cloudwatch/describe-log-streams/route.ts @@ -44,6 +44,12 @@ export async function POST(request: NextRequest) { output: { logStreams: result.logStreams }, }) } catch (error) { + if (error instanceof z.ZodError) { + return NextResponse.json( + { error: error.errors[0]?.message ?? 'Invalid request' }, + { status: 400 } + ) + } const errorMessage = error instanceof Error ? error.message : 'Failed to describe CloudWatch log streams' logger.error('DescribeLogStreams failed', { error: errorMessage }) diff --git a/apps/sim/app/api/tools/cloudwatch/get-log-events/route.ts b/apps/sim/app/api/tools/cloudwatch/get-log-events/route.ts index c42d49e97a..e1a8abcf66 100644 --- a/apps/sim/app/api/tools/cloudwatch/get-log-events/route.ts +++ b/apps/sim/app/api/tools/cloudwatch/get-log-events/route.ts @@ -52,6 +52,12 @@ export async function POST(request: NextRequest) { output: { events: result.events }, }) } catch (error) { + if (error instanceof z.ZodError) { + return NextResponse.json( + { error: error.errors[0]?.message ?? 'Invalid request' }, + { status: 400 } + ) + } const errorMessage = error instanceof Error ? error.message : 'Failed to get CloudWatch log events' logger.error('GetLogEvents failed', { error: errorMessage }) diff --git a/apps/sim/app/api/tools/cloudwatch/get-metric-statistics/route.ts b/apps/sim/app/api/tools/cloudwatch/get-metric-statistics/route.ts index 321092b328..677bafca3c 100644 --- a/apps/sim/app/api/tools/cloudwatch/get-metric-statistics/route.ts +++ b/apps/sim/app/api/tools/cloudwatch/get-metric-statistics/route.ts @@ -89,6 +89,12 @@ export async function POST(request: NextRequest) { }, }) } catch (error) { + if (error instanceof z.ZodError) { + return NextResponse.json( + { error: error.errors[0]?.message ?? 'Invalid request' }, + { status: 400 } + ) + } const errorMessage = error instanceof Error ? error.message : 'Failed to get CloudWatch metric statistics' logger.error('GetMetricStatistics failed', { error: errorMessage }) diff --git a/apps/sim/app/api/tools/cloudwatch/list-metrics/route.ts b/apps/sim/app/api/tools/cloudwatch/list-metrics/route.ts index 09485cb859..36d2c31e2f 100644 --- a/apps/sim/app/api/tools/cloudwatch/list-metrics/route.ts +++ b/apps/sim/app/api/tools/cloudwatch/list-metrics/route.ts @@ -62,6 +62,12 @@ export async function POST(request: NextRequest) { output: { metrics }, }) } catch (error) { + if (error instanceof z.ZodError) { + return NextResponse.json( + { error: error.errors[0]?.message ?? 'Invalid request' }, + { status: 400 } + ) + } const errorMessage = error instanceof Error ? error.message : 'Failed to list CloudWatch metrics' logger.error('ListMetrics failed', { error: errorMessage }) diff --git a/apps/sim/app/api/tools/cloudwatch/query-logs/route.ts b/apps/sim/app/api/tools/cloudwatch/query-logs/route.ts index a471edc20e..75b4dab239 100644 --- a/apps/sim/app/api/tools/cloudwatch/query-logs/route.ts +++ b/apps/sim/app/api/tools/cloudwatch/query-logs/route.ts @@ -63,6 +63,12 @@ export async function POST(request: NextRequest) { }, }) } catch (error) { + if (error instanceof z.ZodError) { + return NextResponse.json( + { error: error.errors[0]?.message ?? 'Invalid request' }, + { status: 400 } + ) + } const errorMessage = error instanceof Error ? error.message : 'CloudWatch Log Insights query failed' logger.error('QueryLogs failed', { error: errorMessage }) diff --git a/apps/sim/app/api/tools/dynamodb/delete/route.ts b/apps/sim/app/api/tools/dynamodb/delete/route.ts index 0002787f37..5b6ab1d5b2 100644 --- a/apps/sim/app/api/tools/dynamodb/delete/route.ts +++ b/apps/sim/app/api/tools/dynamodb/delete/route.ts @@ -41,6 +41,12 @@ export async function POST(request: NextRequest) { message: 'Item deleted successfully', }) } catch (error) { + if (error instanceof z.ZodError) { + return NextResponse.json( + { error: error.errors[0]?.message ?? 'Invalid request' }, + { status: 400 } + ) + } const errorMessage = error instanceof Error ? error.message : 'DynamoDB delete failed' return NextResponse.json({ error: errorMessage }, { status: 500 }) } diff --git a/apps/sim/app/api/tools/dynamodb/get/route.ts b/apps/sim/app/api/tools/dynamodb/get/route.ts index 851f1cb074..1eca9d3f72 100644 --- a/apps/sim/app/api/tools/dynamodb/get/route.ts +++ b/apps/sim/app/api/tools/dynamodb/get/route.ts @@ -48,6 +48,12 @@ export async function POST(request: NextRequest) { item: result.item, }) } catch (error) { + if (error instanceof z.ZodError) { + return NextResponse.json( + { error: error.errors[0]?.message ?? 'Invalid request' }, + { status: 400 } + ) + } const errorMessage = error instanceof Error ? error.message : 'DynamoDB get failed' return NextResponse.json({ error: errorMessage }, { status: 500 }) } diff --git a/apps/sim/app/api/tools/dynamodb/put/route.ts b/apps/sim/app/api/tools/dynamodb/put/route.ts index cb001c5873..2572cdcd5e 100644 --- a/apps/sim/app/api/tools/dynamodb/put/route.ts +++ b/apps/sim/app/api/tools/dynamodb/put/route.ts @@ -36,6 +36,12 @@ export async function POST(request: NextRequest) { item: validatedData.item, }) } catch (error) { + if (error instanceof z.ZodError) { + return NextResponse.json( + { error: error.errors[0]?.message ?? 'Invalid request' }, + { status: 400 } + ) + } const errorMessage = error instanceof Error ? error.message : 'DynamoDB put failed' return NextResponse.json({ error: errorMessage }, { status: 500 }) } diff --git a/apps/sim/app/api/tools/dynamodb/query/route.ts b/apps/sim/app/api/tools/dynamodb/query/route.ts index 06945c1007..3b1fadeee1 100644 --- a/apps/sim/app/api/tools/dynamodb/query/route.ts +++ b/apps/sim/app/api/tools/dynamodb/query/route.ts @@ -51,6 +51,12 @@ export async function POST(request: NextRequest) { count: result.count, }) } catch (error) { + if (error instanceof z.ZodError) { + return NextResponse.json( + { error: error.errors[0]?.message ?? 'Invalid request' }, + { status: 400 } + ) + } const errorMessage = error instanceof Error ? error.message : 'DynamoDB query failed' return NextResponse.json({ error: errorMessage }, { status: 500 }) } diff --git a/apps/sim/app/api/tools/dynamodb/scan/route.ts b/apps/sim/app/api/tools/dynamodb/scan/route.ts index c083faad58..64c47895b0 100644 --- a/apps/sim/app/api/tools/dynamodb/scan/route.ts +++ b/apps/sim/app/api/tools/dynamodb/scan/route.ts @@ -45,6 +45,12 @@ export async function POST(request: NextRequest) { count: result.count, }) } catch (error) { + if (error instanceof z.ZodError) { + return NextResponse.json( + { error: error.errors[0]?.message ?? 'Invalid request' }, + { status: 400 } + ) + } const errorMessage = error instanceof Error ? error.message : 'DynamoDB scan failed' return NextResponse.json({ error: errorMessage }, { status: 500 }) } diff --git a/apps/sim/app/api/tools/dynamodb/update/route.ts b/apps/sim/app/api/tools/dynamodb/update/route.ts index 07abcc2564..3a5892fe61 100644 --- a/apps/sim/app/api/tools/dynamodb/update/route.ts +++ b/apps/sim/app/api/tools/dynamodb/update/route.ts @@ -50,6 +50,12 @@ export async function POST(request: NextRequest) { item: result.attributes, }) } catch (error) { + if (error instanceof z.ZodError) { + return NextResponse.json( + { error: error.errors[0]?.message ?? 'Invalid request' }, + { status: 400 } + ) + } const errorMessage = error instanceof Error ? error.message : 'DynamoDB update failed' return NextResponse.json({ error: errorMessage }, { status: 500 }) } diff --git a/apps/sim/app/api/tools/google_drive/download/route.ts b/apps/sim/app/api/tools/google_drive/download/route.ts index 2a9730dcad..070d61f4f8 100644 --- a/apps/sim/app/api/tools/google_drive/download/route.ts +++ b/apps/sim/app/api/tools/google_drive/download/route.ts @@ -240,6 +240,12 @@ export async function POST(request: NextRequest) { }, }) } catch (error) { + if (error instanceof z.ZodError) { + return NextResponse.json( + { error: error.errors[0]?.message ?? 'Invalid request' }, + { status: 400 } + ) + } logger.error(`[${requestId}] Error downloading Google Drive file:`, error) return NextResponse.json( { diff --git a/apps/sim/app/api/tools/onedrive/download/route.ts b/apps/sim/app/api/tools/onedrive/download/route.ts index a50338af55..87ee62047b 100644 --- a/apps/sim/app/api/tools/onedrive/download/route.ts +++ b/apps/sim/app/api/tools/onedrive/download/route.ts @@ -165,6 +165,12 @@ export async function POST(request: NextRequest) { }, }) } catch (error) { + if (error instanceof z.ZodError) { + return NextResponse.json( + { error: error.errors[0]?.message ?? 'Invalid request' }, + { status: 400 } + ) + } logger.error(`[${requestId}] Error downloading OneDrive file:`, error) return NextResponse.json( { diff --git a/apps/sim/app/api/tools/outlook/draft/route.ts b/apps/sim/app/api/tools/outlook/draft/route.ts index eeee0f14e1..94da1162a5 100644 --- a/apps/sim/app/api/tools/outlook/draft/route.ts +++ b/apps/sim/app/api/tools/outlook/draft/route.ts @@ -176,6 +176,12 @@ export async function POST(request: NextRequest) { }, }) } catch (error) { + if (error instanceof z.ZodError) { + return NextResponse.json( + { error: error.errors[0]?.message ?? 'Invalid request' }, + { status: 400 } + ) + } logger.error(`[${requestId}] Error creating Outlook draft:`, error) return NextResponse.json( { diff --git a/apps/sim/app/api/tools/outlook/send/route.ts b/apps/sim/app/api/tools/outlook/send/route.ts index f90f62518a..a11a954196 100644 --- a/apps/sim/app/api/tools/outlook/send/route.ts +++ b/apps/sim/app/api/tools/outlook/send/route.ts @@ -189,6 +189,12 @@ export async function POST(request: NextRequest) { }, }) } catch (error) { + if (error instanceof z.ZodError) { + return NextResponse.json( + { error: error.errors[0]?.message ?? 'Invalid request' }, + { status: 400 } + ) + } logger.error(`[${requestId}] Error sending Outlook email:`, error) return NextResponse.json( { diff --git a/apps/sim/app/api/tools/slack/download/route.ts b/apps/sim/app/api/tools/slack/download/route.ts index 45c34bcd11..8c2d59e24d 100644 --- a/apps/sim/app/api/tools/slack/download/route.ts +++ b/apps/sim/app/api/tools/slack/download/route.ts @@ -158,6 +158,12 @@ export async function POST(request: NextRequest) { }, }) } catch (error) { + if (error instanceof z.ZodError) { + return NextResponse.json( + { error: error.errors[0]?.message ?? 'Invalid request' }, + { status: 400 } + ) + } logger.error(`[${requestId}] Error downloading Slack file:`, error) return NextResponse.json( { diff --git a/apps/sim/app/api/tools/slack/send-ephemeral/route.ts b/apps/sim/app/api/tools/slack/send-ephemeral/route.ts index 6d443e5039..36d87c757c 100644 --- a/apps/sim/app/api/tools/slack/send-ephemeral/route.ts +++ b/apps/sim/app/api/tools/slack/send-ephemeral/route.ts @@ -84,6 +84,12 @@ export async function POST(request: NextRequest) { }, }) } catch (error) { + if (error instanceof z.ZodError) { + return NextResponse.json( + { error: error.errors[0]?.message ?? 'Invalid request' }, + { status: 400 } + ) + } logger.error(`[${requestId}] Error sending ephemeral message:`, error) return NextResponse.json( { diff --git a/apps/sim/app/api/tools/slack/send-message/route.ts b/apps/sim/app/api/tools/slack/send-message/route.ts index a6b8a3db71..0234d0fbe1 100644 --- a/apps/sim/app/api/tools/slack/send-message/route.ts +++ b/apps/sim/app/api/tools/slack/send-message/route.ts @@ -77,6 +77,12 @@ export async function POST(request: NextRequest) { return NextResponse.json({ success: true, output: result.output }) } catch (error) { + if (error instanceof z.ZodError) { + return NextResponse.json( + { error: error.errors[0]?.message ?? 'Invalid request' }, + { status: 400 } + ) + } logger.error(`[${requestId}] Error sending Slack message:`, error) return NextResponse.json( { From 088cf23862d0cb5918756d9ff6adc9cfa3016a02 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Wed, 8 Apr 2026 00:12:30 -0700 Subject: [PATCH 3/3] fix(api): add success:false to ZodError responses for consistency 7 routes used { success: false, error: ... } in their generic error handler but our ZodError handler only returned { error: ... }. Aligned the ZodError response shape to match. Co-Authored-By: Claude Opus 4.6 --- apps/sim/app/api/tools/google_drive/download/route.ts | 2 +- apps/sim/app/api/tools/onedrive/download/route.ts | 2 +- apps/sim/app/api/tools/outlook/draft/route.ts | 2 +- apps/sim/app/api/tools/outlook/send/route.ts | 2 +- apps/sim/app/api/tools/slack/download/route.ts | 2 +- apps/sim/app/api/tools/slack/send-ephemeral/route.ts | 2 +- apps/sim/app/api/tools/slack/send-message/route.ts | 2 +- apps/sim/app/workspace/[workspaceId]/home/home.tsx | 4 ---- 8 files changed, 7 insertions(+), 11 deletions(-) diff --git a/apps/sim/app/api/tools/google_drive/download/route.ts b/apps/sim/app/api/tools/google_drive/download/route.ts index 070d61f4f8..e4131423f9 100644 --- a/apps/sim/app/api/tools/google_drive/download/route.ts +++ b/apps/sim/app/api/tools/google_drive/download/route.ts @@ -242,7 +242,7 @@ export async function POST(request: NextRequest) { } catch (error) { if (error instanceof z.ZodError) { return NextResponse.json( - { error: error.errors[0]?.message ?? 'Invalid request' }, + { success: false, error: error.errors[0]?.message ?? 'Invalid request' }, { status: 400 } ) } diff --git a/apps/sim/app/api/tools/onedrive/download/route.ts b/apps/sim/app/api/tools/onedrive/download/route.ts index 87ee62047b..2cc268ffd5 100644 --- a/apps/sim/app/api/tools/onedrive/download/route.ts +++ b/apps/sim/app/api/tools/onedrive/download/route.ts @@ -167,7 +167,7 @@ export async function POST(request: NextRequest) { } catch (error) { if (error instanceof z.ZodError) { return NextResponse.json( - { error: error.errors[0]?.message ?? 'Invalid request' }, + { success: false, error: error.errors[0]?.message ?? 'Invalid request' }, { status: 400 } ) } diff --git a/apps/sim/app/api/tools/outlook/draft/route.ts b/apps/sim/app/api/tools/outlook/draft/route.ts index 94da1162a5..801b3b9086 100644 --- a/apps/sim/app/api/tools/outlook/draft/route.ts +++ b/apps/sim/app/api/tools/outlook/draft/route.ts @@ -178,7 +178,7 @@ export async function POST(request: NextRequest) { } catch (error) { if (error instanceof z.ZodError) { return NextResponse.json( - { error: error.errors[0]?.message ?? 'Invalid request' }, + { success: false, error: error.errors[0]?.message ?? 'Invalid request' }, { status: 400 } ) } diff --git a/apps/sim/app/api/tools/outlook/send/route.ts b/apps/sim/app/api/tools/outlook/send/route.ts index a11a954196..f2d39ef11e 100644 --- a/apps/sim/app/api/tools/outlook/send/route.ts +++ b/apps/sim/app/api/tools/outlook/send/route.ts @@ -191,7 +191,7 @@ export async function POST(request: NextRequest) { } catch (error) { if (error instanceof z.ZodError) { return NextResponse.json( - { error: error.errors[0]?.message ?? 'Invalid request' }, + { success: false, error: error.errors[0]?.message ?? 'Invalid request' }, { status: 400 } ) } diff --git a/apps/sim/app/api/tools/slack/download/route.ts b/apps/sim/app/api/tools/slack/download/route.ts index 8c2d59e24d..83a44386d4 100644 --- a/apps/sim/app/api/tools/slack/download/route.ts +++ b/apps/sim/app/api/tools/slack/download/route.ts @@ -160,7 +160,7 @@ export async function POST(request: NextRequest) { } catch (error) { if (error instanceof z.ZodError) { return NextResponse.json( - { error: error.errors[0]?.message ?? 'Invalid request' }, + { success: false, error: error.errors[0]?.message ?? 'Invalid request' }, { status: 400 } ) } diff --git a/apps/sim/app/api/tools/slack/send-ephemeral/route.ts b/apps/sim/app/api/tools/slack/send-ephemeral/route.ts index 36d87c757c..1387290c6a 100644 --- a/apps/sim/app/api/tools/slack/send-ephemeral/route.ts +++ b/apps/sim/app/api/tools/slack/send-ephemeral/route.ts @@ -86,7 +86,7 @@ export async function POST(request: NextRequest) { } catch (error) { if (error instanceof z.ZodError) { return NextResponse.json( - { error: error.errors[0]?.message ?? 'Invalid request' }, + { success: false, error: error.errors[0]?.message ?? 'Invalid request' }, { status: 400 } ) } diff --git a/apps/sim/app/api/tools/slack/send-message/route.ts b/apps/sim/app/api/tools/slack/send-message/route.ts index 0234d0fbe1..5520a280f6 100644 --- a/apps/sim/app/api/tools/slack/send-message/route.ts +++ b/apps/sim/app/api/tools/slack/send-message/route.ts @@ -79,7 +79,7 @@ export async function POST(request: NextRequest) { } catch (error) { if (error instanceof z.ZodError) { return NextResponse.json( - { error: error.errors[0]?.message ?? 'Invalid request' }, + { success: false, error: error.errors[0]?.message ?? 'Invalid request' }, { status: 400 } ) } diff --git a/apps/sim/app/workspace/[workspaceId]/home/home.tsx b/apps/sim/app/workspace/[workspaceId]/home/home.tsx index e79e307def..132d87b2a9 100644 --- a/apps/sim/app/workspace/[workspaceId]/home/home.tsx +++ b/apps/sim/app/workspace/[workspaceId]/home/home.tsx @@ -273,10 +273,6 @@ export function Home({ chatId }: HomeProps = {}) { return context.tableId ? { type: 'table', id: context.tableId } : null case 'file': return context.fileId ? { type: 'file', id: context.fileId } : null - case 'folder': - return context.folderId ? { type: 'folder', id: context.folderId } : null - case 'past_chat': - return context.chatId ? { type: 'task', id: context.chatId } : null default: return null }