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 f9f997d618e..f49bc16247d 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 83e9845b75c..394bbda2b87 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 b043db11414..129f4794dc4 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 d89488371db..260cc73dc0c 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 c9f74ca2161..326e03711bb 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 096afee99cb..958d09b1735 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 6af793cbe01..0555246aa8e 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 2f3422b36e2..0a7558d314a 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 132d87b2a9e..e79e307def4 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 5113c796016..87f17764cf0 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 b47611b0cfb..d267bb01fa3 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 b838512a437..a3108eebffc 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 30cf207d7e6..d8fc946b519 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 30d05166816..a21c3e70410 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 9abdad4e170..a5e6edeeaa3 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 ca22c8e8567..dfc65171362 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 e2a8b4428ed..1264d813fdf 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 0ab6c4aad8d..3fc65ab5bfd 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 a10f46c4efa..fcb29be5289 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 d74ad6de266..223e51617b9 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 c42d49e97ab..e1a8abcf666 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 321092b3283..677bafca3ca 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 09485cb8590..36d2c31e2fa 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 a471edc20e8..75b4dab2395 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 0002787f373..5b6ab1d5b20 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 851f1cb0740..1eca9d3f72e 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 cb001c5873a..2572cdcd5e7 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 06945c10070..3b1fadeee12 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 c083faad584..64c47895b0a 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 07abcc25648..3a5892fe61a 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 2a9730dcada..070d61f4f87 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 a50338af557..87ee62047bc 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 eeee0f14e17..94da1162a56 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 f90f62518a8..a11a954196f 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 45c34bcd11d..8c2d59e24d5 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 6d443e5039a..36d87c757cd 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 a6b8a3db71c..0234d0fbe1d 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 070d61f4f87..e4131423f91 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 87ee62047bc..2cc268ffd5e 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 94da1162a56..801b3b90869 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 a11a954196f..f2d39ef11e6 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 8c2d59e24d5..83a44386d4d 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 36d87c757cd..1387290c6ae 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 0234d0fbe1d..5520a280f6e 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 e79e307def4..132d87b2a9e 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 }