Skip to content

Commit c3808b1

Browse files
committed
error on partial upload failures
1 parent 2c35579 commit c3808b1

4 files changed

Lines changed: 109 additions & 30 deletions

File tree

apps/sim/app/api/tools/sharepoint/upload/route.ts

Lines changed: 43 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@ import { withRouteHandler } from '@/lib/core/utils/with-route-handler'
1010
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
1111
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
1212
import type { MicrosoftGraphDriveItem } from '@/tools/onedrive/types'
13+
import type { SharepointSkippedFile, SharepointUploadError } from '@/tools/sharepoint/types'
1314

1415
export const dynamic = 'force-dynamic'
1516

1617
const logger = createLogger('SharepointUploadAPI')
18+
const MAX_SHAREPOINT_UPLOAD_BYTES = 250 * 1024 * 1024
1719

1820
export const POST = withRouteHandler(async (request: NextRequest) => {
1921
const requestId = generateRequestId()
@@ -76,6 +78,8 @@ export const POST = withRouteHandler(async (request: NextRequest) => {
7678
const siteId = validatedData.siteId.trim() || 'root'
7779
const driveId = validatedData.driveId?.trim() || null
7880
const uploadedFiles: MicrosoftGraphDriveItem[] = []
81+
const skippedFiles: SharepointSkippedFile[] = []
82+
const errors: SharepointUploadError[] = []
7983

8084
for (const userFile of userFiles) {
8185
logger.info(`[${requestId}] Uploading file: ${userFile.name}`)
@@ -87,10 +91,16 @@ export const POST = withRouteHandler(async (request: NextRequest) => {
8791

8892
const fileSizeMB = buffer.length / (1024 * 1024)
8993

90-
if (fileSizeMB > 250) {
94+
if (buffer.length > MAX_SHAREPOINT_UPLOAD_BYTES) {
9195
logger.warn(
9296
`[${requestId}] File ${fileName} is ${fileSizeMB.toFixed(2)}MB, exceeds 250MB limit`
9397
)
98+
skippedFiles.push({
99+
name: fileName,
100+
size: buffer.length,
101+
limit: MAX_SHAREPOINT_UPLOAD_BYTES,
102+
reason: 'File exceeds the 250 MB Microsoft Graph small upload limit',
103+
})
94104
continue
95105
}
96106

@@ -155,13 +165,12 @@ export const POST = withRouteHandler(async (request: NextRequest) => {
155165
error?: { message?: string }
156166
}
157167
logger.error(`[${requestId}] Failed to replace file ${fileName}:`, replaceErrorData)
158-
return NextResponse.json(
159-
{
160-
success: false,
161-
error: replaceErrorData.error?.message || `Failed to replace file: ${fileName}`,
162-
},
163-
{ status: replaceResponse.status }
164-
)
168+
errors.push({
169+
name: fileName,
170+
status: replaceResponse.status,
171+
error: replaceErrorData.error?.message || `Failed to replace file: ${fileName}`,
172+
})
173+
continue
165174
}
166175

167176
const replaceData = (await replaceResponse.json()) as {
@@ -185,15 +194,14 @@ export const POST = withRouteHandler(async (request: NextRequest) => {
185194
continue
186195
}
187196

188-
return NextResponse.json(
189-
{
190-
success: false,
191-
error:
192-
(errorData as { error?: { message?: string } }).error?.message ||
193-
`Failed to upload file: ${fileName}`,
194-
},
195-
{ status: uploadResponse.status }
196-
)
197+
errors.push({
198+
name: fileName,
199+
status: uploadResponse.status,
200+
error:
201+
(errorData as { error?: { message?: string } }).error?.message ||
202+
`Failed to upload file: ${fileName}`,
203+
})
204+
continue
197205
}
198206

199207
const uploadData = (await uploadResponse.json()) as MicrosoftGraphDriveItem
@@ -210,22 +218,33 @@ export const POST = withRouteHandler(async (request: NextRequest) => {
210218
}
211219

212220
if (uploadedFiles.length === 0) {
213-
return NextResponse.json(
214-
{
215-
success: false,
216-
error: 'No files were uploaded successfully',
221+
return NextResponse.json({
222+
success: false,
223+
error: 'No files were uploaded successfully',
224+
output: {
225+
uploadedFiles,
226+
fileCount: 0,
227+
skippedFiles,
228+
skippedCount: skippedFiles.length,
229+
errors,
217230
},
218-
{ status: 400 }
219-
)
231+
})
220232
}
221233

222-
logger.info(`[${requestId}] Successfully uploaded ${uploadedFiles.length} file(s)`)
234+
logger.info(`[${requestId}] Completed SharePoint upload`, {
235+
uploadedCount: uploadedFiles.length,
236+
skippedCount: skippedFiles.length,
237+
errorCount: errors.length,
238+
})
223239

224240
return NextResponse.json({
225241
success: true,
226242
output: {
227243
uploadedFiles,
228244
fileCount: uploadedFiles.length,
245+
skippedFiles,
246+
skippedCount: skippedFiles.length,
247+
errors,
229248
},
230249
})
231250
} catch (error) {

apps/sim/blocks/blocks/sharepoint.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,6 +1033,15 @@ Return ONLY the JSON object - no explanations, no markdown, no extra text.`,
10331033
description: 'Array of uploaded file objects with id, name, webUrl, size',
10341034
},
10351035
fileCount: { type: 'number', description: 'Number of files uploaded' },
1036+
skippedFiles: {
1037+
type: 'json',
1038+
description: 'Array of skipped upload files (name, size, limit, reason)',
1039+
},
1040+
skippedCount: { type: 'number', description: 'Number of files skipped' },
1041+
errors: {
1042+
type: 'json',
1043+
description: 'Array of per-file upload errors (name, error, status)',
1044+
},
10361045
nextPageUrl: {
10371046
type: 'string',
10381047
description: 'Microsoft Graph @odata.nextLink URL for the next page of results',

apps/sim/tools/sharepoint/types.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,9 +285,25 @@ export interface SharepointUploadedFile {
285285
lastModifiedDateTime?: string
286286
}
287287

288+
export interface SharepointSkippedFile {
289+
name: string
290+
size: number
291+
limit: number
292+
reason: string
293+
}
294+
295+
export interface SharepointUploadError {
296+
name: string
297+
error: string
298+
status?: number
299+
}
300+
288301
export interface SharepointUploadFileResponse extends ToolResponse {
289302
output: {
290303
uploadedFiles: SharepointUploadedFile[]
291304
fileCount: number
305+
skippedFiles?: SharepointSkippedFile[]
306+
skippedCount?: number
307+
errors?: SharepointUploadError[]
292308
}
293309
}

apps/sim/tools/sharepoint/upload_file.ts

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,15 +74,17 @@ export const uploadFileTool: ToolConfig<SharepointToolParams, SharepointUploadFi
7474

7575
transformResponse: async (response: Response) => {
7676
const data = await response.json()
77-
if (!data.success) {
78-
throw new Error(data.error || 'Failed to upload files to SharePoint')
79-
}
77+
const output = data.output ?? {}
8078
return {
81-
success: true,
79+
success: Boolean(data.success),
8280
output: {
83-
uploadedFiles: data.output.uploadedFiles,
84-
fileCount: data.output.fileCount,
81+
uploadedFiles: output.uploadedFiles ?? [],
82+
fileCount: output.fileCount ?? 0,
83+
skippedFiles: output.skippedFiles ?? [],
84+
skippedCount: output.skippedCount ?? 0,
85+
errors: output.errors ?? [],
8586
},
87+
error: data.success ? undefined : data.error || 'Failed to upload files to SharePoint',
8688
}
8789
},
8890

@@ -106,5 +108,38 @@ export const uploadFileTool: ToolConfig<SharepointToolParams, SharepointUploadFi
106108
type: 'number',
107109
description: 'Number of files uploaded',
108110
},
111+
skippedFiles: {
112+
type: 'array',
113+
description: 'Files that were skipped before upload',
114+
items: {
115+
type: 'object',
116+
properties: {
117+
name: { type: 'string', description: 'File name' },
118+
size: { type: 'number', description: 'File size in bytes' },
119+
limit: { type: 'number', description: 'Upload size limit in bytes' },
120+
reason: { type: 'string', description: 'Reason the file was skipped' },
121+
},
122+
},
123+
},
124+
skippedCount: {
125+
type: 'number',
126+
description: 'Number of files skipped',
127+
},
128+
errors: {
129+
type: 'array',
130+
description: 'Per-file upload errors',
131+
items: {
132+
type: 'object',
133+
properties: {
134+
name: { type: 'string', description: 'File name' },
135+
error: { type: 'string', description: 'Error message' },
136+
status: {
137+
type: 'number',
138+
description: 'HTTP status from Microsoft Graph',
139+
optional: true,
140+
},
141+
},
142+
},
143+
},
109144
},
110145
}

0 commit comments

Comments
 (0)