Skip to content

Commit e9c1514

Browse files
committed
fix: update Marketo error handling to distinguish non-retryable errors
1 parent 6f393e9 commit e9c1514

1 file changed

Lines changed: 66 additions & 24 deletions

File tree

  • packages/destination-actions/src/destinations/marketo-static-lists

packages/destination-actions/src/destinations/marketo-static-lists/functions.ts

Lines changed: 66 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -321,23 +321,65 @@ function extractLeadIds(leads: MarketoLeads[] = []) {
321321
return ids
322322
}
323323

324-
// Marketo error codes that indicate transient/temporary failures which should be retried.
324+
// Marketo error codes that are definitively non-retryable (bad input / permanent state).
325+
// Unknown/future codes default to retryable to avoid silently dropping events.
326+
// Explicitly retryable (NOT listed here): 1016 (too many imports), 1019 (import in progress),
327+
// 1020 (daily clone quota), 1029 (bulk extract queue/quota).
325328
// Reference: https://experienceleague.adobe.com/en/docs/marketo-developer/marketo/rest/error-codes
326-
const MARKETO_RETRYABLE_CODES = new Set([
327-
'500', // Internal server error
328-
'502', // Bad gateway / timeout
329-
'604', // Request timeout
330-
'606', // Rate limit exceeded (>100 calls per 20 seconds)
331-
'607', // Daily quota exhausted
332-
'608', // API temporarily unavailable
333-
'611', // Unhandled system exception
334-
'614', // Unreachable subscription
335-
'615', // Concurrent access limit exceeded
336-
'713', // Transient error – system resource temporarily unavailable
337-
'719', // Lock wait timeout
338-
'1019', // Batch import in progress on list
339-
'1016', // Too many imports in progress
340-
'1029' // Queue/export limit exceeded
329+
const MARKETO_NON_RETRYABLE_CODES = new Set([
330+
// HTTP-level errors
331+
'603', // Access denied
332+
'605', // HTTP method not supported
333+
'609', // Invalid JSON
334+
'610', // Requested resource not found
335+
'612', // Invalid content type
336+
'613', // Invalid multipart request
337+
'616', // Not a valid subscription type
338+
// REST API parameter/field errors
339+
'701', // Mandatory field value missing
340+
'702', // No data found for search scenario
341+
'703', // Feature not enabled for subscription
342+
'704', // Invalid date format
343+
'709', // Business rule violation
344+
'710', // Parent folder not found
345+
'711', // Incompatible folder type
346+
'712', // Person merge failed
347+
'714', // Unable to find default record type
348+
'718', // ExternalSalesPersonID not found
349+
// Application-level errors
350+
'1001', // Invalid value — type mismatch
351+
'1002', // Missing required parameter
352+
'1003', // Invalid data
353+
'1004', // Lead not found (updateOnly mode)
354+
'1005', // Lead already exists (createOnly mode)
355+
'1006', // Field not found
356+
'1007', // Multiple leads match lookup criteria
357+
'1008', // Access denied to partition
358+
'1009', // Partition name must be specified
359+
'1010', // Partition update not allowed
360+
'1011', // Field not supported as filter/lookup
361+
'1012', // Invalid cookie value
362+
'1013', // Object not found
363+
'1014', // Failed to create object
364+
'1015', // Lead not in list
365+
'1017', // Object already exists
366+
'1018', // CRM integration enabled — action not allowed
367+
'1021', // Company update not allowed during syncLead
368+
'1022', // Object in use — delete not allowed
369+
'1025', // Program status not found
370+
'1026', // Custom object not enabled for subscription
371+
'1027', // Max activity type limit reached
372+
'1028', // Max field limit reached (custom activity attributes)
373+
'1035', // Unsupported filter type for bulk extract
374+
'1036', // Duplicate object found in input
375+
'1037', // Lead skipped — already in or past target status
376+
'1042', // Invalid runAt date (too far in future)
377+
'1048', // Custom object discard draft failed
378+
'1049', // Activity attributes array too long
379+
'1076', // Merge leads — duplicate record in CRM
380+
'1077', // Merge leads — SFDC field too long
381+
'1078', // Merge leads — deleted entity or field filter mismatch
382+
'1079' // Merge leads — personalized URL conflict
341383
])
342384

343385
function parseErrorResponse(response: MarketoResponse) {
@@ -355,11 +397,11 @@ function parseErrorResponse(response: MarketoResponse) {
355397
throw new IntegrationError(message, 'INVALID_AUTHENTICATION', 401)
356398
}
357399

358-
if (MARKETO_RETRYABLE_CODES.has(code)) {
359-
throw new RetryableError(message)
400+
if (MARKETO_NON_RETRYABLE_CODES.has(code)) {
401+
throw new IntegrationError(message, ErrorCodes.BAD_REQUEST, 400)
360402
}
361403

362-
throw new IntegrationError(message, ErrorCodes.PAYLOAD_VALIDATION_FAILED, 400)
404+
throw new RetryableError(message)
363405
}
364406

365407
function parseErrorResponseBatch(response: MarketoResponse, payloadSize: number) {
@@ -379,18 +421,18 @@ function parseErrorResponseBatch(response: MarketoResponse, payloadSize: number)
379421
throw new IntegrationError(message, ErrorCodes.INVALID_AUTHENTICATION, 401)
380422
}
381423

382-
if (MARKETO_RETRYABLE_CODES.has(code)) {
424+
if (MARKETO_NON_RETRYABLE_CODES.has(code)) {
383425
return buildMultiStatusErrorResponse(payloadSize, {
384-
status: 500,
385-
errortype: ErrorCodes.RETRYABLE_ERROR,
426+
status: 400,
427+
errortype: ErrorCodes.BAD_REQUEST,
386428
body: response.errors[0] as unknown as JSONLikeObject,
387429
errormessage: message
388430
})
389431
}
390432

391433
return buildMultiStatusErrorResponse(payloadSize, {
392-
status: 400,
393-
errortype: ErrorCodes.PAYLOAD_VALIDATION_FAILED,
434+
status: 500,
435+
errortype: ErrorCodes.RETRYABLE_ERROR,
394436
body: response.errors[0] as unknown as JSONLikeObject,
395437
errormessage: message
396438
})

0 commit comments

Comments
 (0)