Skip to content

Commit 5abdb7c

Browse files
committed
fix(uploads): retry transient DirectUploadErrors at outer KB level
The KB outer retry only triggered on isNetworkError, missing transient 5xx from S3/Azure (DirectUploadError code DIRECT_UPLOAD_ERROR or MULTIPART_ERROR). Adds isTransientUploadError and retries on it, restoring resilience for small-file presigned PUTs against flaky cloud storage.
1 parent 92f841f commit 5abdb7c

2 files changed

Lines changed: 13 additions & 1 deletion

File tree

apps/sim/app/workspace/[workspaceId]/knowledge/hooks/use-knowledge-upload.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { sleep } from '@sim/utils/helpers'
44
import { useQueryClient } from '@tanstack/react-query'
55
import {
66
DirectUploadError,
7+
isTransientUploadError,
78
LARGE_FILE_THRESHOLD,
89
MULTIPART_MAX_RETRIES,
910
MULTIPART_RETRY_BACKOFF,
@@ -266,7 +267,8 @@ export function useKnowledgeUpload(options: UseKnowledgeUploadOptions = {}) {
266267
return buildUploadedFile(file, toAbsoluteUrl(filePath))
267268
}
268269

269-
if (isAbortError(error) || !isNetworkError(error) || attempt >= MULTIPART_MAX_RETRIES) {
270+
const retryable = isNetworkError(error) || isTransientUploadError(error)
271+
if (isAbortError(error) || !retryable || attempt >= MULTIPART_MAX_RETRIES) {
270272
throw error
271273
}
272274

apps/sim/lib/uploads/client/direct-upload.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,16 @@ export class DirectUploadError extends Error {
6363
}
6464
}
6565

66+
/**
67+
* Transport-level upload errors worth retrying at the outer level: timeouts,
68+
* 5xx from the storage backend, and per-part failures whose inner retry was
69+
* exhausted. Excludes deterministic failures (`PRESIGNED_URL_ERROR`,
70+
* `FALLBACK_REQUIRED`) and aborts.
71+
*/
72+
export const isTransientUploadError = (error: unknown): boolean =>
73+
error instanceof DirectUploadError &&
74+
(error.code === 'DIRECT_UPLOAD_ERROR' || error.code === 'MULTIPART_ERROR')
75+
6676
const calculateUploadTimeoutMs = (fileSize: number): number => {
6777
const sizeInMb = fileSize / (1024 * 1024)
6878
const dynamicBudget = BASE_TIMEOUT_MS + sizeInMb * TIMEOUT_PER_MB_MS

0 commit comments

Comments
 (0)