@@ -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
343385function 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
365407function 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