Skip to content

Commit 224476a

Browse files
committed
fix(resume): withhold unsafe resume failure messages on the legacy route
Also drop two unused exports from the v2 Project file search contract that fail check:unused-exports on staging.
1 parent 94fe01e commit 224476a

3 files changed

Lines changed: 17 additions & 12 deletions

File tree

‎apps/sim/app/api/resume/[workflowId]/[executionId]/[contextId]/route.test.ts‎

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -513,12 +513,17 @@ describe('POST /api/resume/[workflowId]/[executionId]/[contextId]', () => {
513513
})
514514

515515
it.each([
516-
{ statusCode: 402, message: 'Member usage limit reached', retryable: false },
517-
{ statusCode: 429, message: 'Target concurrency full', retryable: true },
518-
{ statusCode: 503, message: 'Usage admission unavailable', retryable: true },
516+
{ statusCode: 402, message: 'Member usage limit reached', retryable: false, body: undefined },
517+
{ statusCode: 429, message: 'Target concurrency full', retryable: true, body: undefined },
518+
{
519+
statusCode: 503,
520+
message: 'Usage admission unavailable',
521+
retryable: true,
522+
body: 'Internal server error',
523+
},
519524
])(
520525
'leaves the pause and queued input untouched when readmission returns $statusCode',
521-
async ({ statusCode, message, retryable }) => {
526+
async ({ statusCode, message, retryable, body }) => {
522527
mockPreprocessExecution.mockResolvedValueOnce({
523528
success: false,
524529
error: { statusCode, message, retryable },
@@ -528,7 +533,7 @@ describe('POST /api/resume/[workflowId]/[executionId]/[contextId]', () => {
528533
const response = await POST(request, context)
529534

530535
expect(response.status).toBe(statusCode)
531-
expect(await response.json()).toEqual({ error: message })
536+
expect(await response.json()).toEqual({ error: body ?? message })
532537
expect(mockEnqueueOrStartResume).not.toHaveBeenCalled()
533538
}
534539
)
@@ -543,7 +548,7 @@ describe('POST /api/resume/[workflowId]/[executionId]/[contextId]', () => {
543548

544549
expect(response.status).toBe(500)
545550
expect(await response.json()).toEqual({
546-
error: 'Paused execution billing attribution is missing or invalid',
551+
error: 'Internal server error',
547552
})
548553
expect(mockPreprocessExecution).not.toHaveBeenCalled()
549554
expect(mockEnqueueOrStartResume).not.toHaveBeenCalled()
@@ -576,7 +581,7 @@ describe('POST /api/resume/[workflowId]/[executionId]/[contextId]', () => {
576581

577582
expect(response.status).toBe(500)
578583
expect(await response.json()).toEqual({
579-
error: 'Paused execution billing attribution does not match its workspace or actor',
584+
error: 'Internal server error',
580585
})
581586
expect(mockPreprocessExecution).not.toHaveBeenCalled()
582587
expect(mockEnqueueOrStartResume).not.toHaveBeenCalled()
@@ -593,7 +598,7 @@ describe('POST /api/resume/[workflowId]/[executionId]/[contextId]', () => {
593598

594599
expect(response.status).toBe(500)
595600
expect(await response.json()).toEqual({
596-
error: 'Paused execution snapshot does not match the requested workflow or execution',
601+
error: 'Internal server error',
597602
})
598603
expect(mockPreprocessExecution).not.toHaveBeenCalled()
599604
expect(mockEnqueueOrStartResume).not.toHaveBeenCalled()

‎apps/sim/app/api/resume/[workflowId]/[executionId]/[contextId]/route.ts‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,9 @@ export const POST = withRouteHandler(
143143
})
144144
}
145145
if (error instanceof ResumeWorkflowExecutionError) {
146-
return NextResponse.json({ error: error.message }, { status: error.statusCode })
146+
// Keep the status so a retryable 503 stays retryable; only the message is withheld.
147+
const message = error.safeForPublicApi ? error.message : 'Internal server error'
148+
return NextResponse.json({ error: message }, { status: error.statusCode })
147149
}
148150
throw error
149151
}

‎apps/sim/lib/api/contracts/v2/project-file-search.ts‎

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import type { z } from 'zod'
21
import { defineRouteContract } from '@/lib/api/contracts/types'
32
import {
43
v2FileSearchResultsSchema,
@@ -7,14 +6,13 @@ import {
76
import { v2ProjectFilesParamsSchema } from '@/lib/api/contracts/v2/project-files'
87
import { v2DataResponse } from '@/lib/api/contracts/v2/shared'
98

10-
export const v2SearchProjectFileContentQuerySchema = v2SearchFileContentQuerySchema
9+
const v2SearchProjectFileContentQuerySchema = v2SearchFileContentQuerySchema
1110
.omit({ workspaceId: true })
1211
.extend({
1312
folderPaths: v2SearchFileContentQuerySchema.shape.folderPaths.describe(
1413
'Comma-separated folder paths within the Project. Omit to search the entire Project; index coverage applies to the selected folders.'
1514
),
1615
})
17-
export type V2SearchProjectFileContentQuery = z.output<typeof v2SearchProjectFileContentQuerySchema>
1816

1917
export const v2SearchProjectFileContentContract = defineRouteContract({
2018
method: 'GET',

0 commit comments

Comments
 (0)