Skip to main content

Integration item parked

Fires when a failed Lattice integration item is parked in the integration dead-letter queue for manual review, the terminal state an operator has to act on. Items reach the queue when a Lattice asynchronous operation or a file ingestion segment fails; a non-retryable failure is parked straight away, and a retryable one is parked once the dead-letter retry sweep has used up its attempts. The Lattice dead-letter retry background process runs that sweep every 5 minutes, so there is nothing to schedule, but retryable failures raise this event only while it (or a scheduled sweep in its place) runs. Monitoring tools such as Power Automate or a Logic App can subscribe to raise an incident or notify the integration team. The payload carries only non-sensitive identification and diagnostic fields: never the original request payload, the original request ID, the source reference, or any credential.

Event classMGCLatticeIntegrationFailureBusinessEvent
Contract classMGCLatticeIntegrationFailureBusinessEventContract
CategorySystem administration
ModuleModuleAxapta::SystemAdministration
Label IDsIntegrationFailureBusinessEventName / IntegrationFailureBusinessEventDesc
TriggerMGCLatticeIntegrationDlqAlert.onParked() -> a dead-letter row has just moved to Parked (at enqueue, or when the retry sweep exhausts its attempts)

Trigger / Hook​

  • Send site: MGCLatticeIntegrationDlqAlert.raiseBusinessEvent(), called from onParked() (via the static onParkedStatic()). onParked() returns without doing anything when the dead-letter record is empty. This business event is the only alert Lattice raises when an item is parked: Lattice sends no email of its own. To have someone emailed, subscribe a Power Automate flow or a Logic App to this event.
  • It's called from the two places that park a dead-letter row and alert, each time after that row's transaction has committed:
    1. MGCLatticeIntegrationDlqManager::enqueue(): when a failure is enqueued as non-retryable it's inserted directly with status Parked. File ingestion segment failures are always enqueued this way; asynchronous operation failures are when the operation reports them as non-retryable. Enqueue is idempotent per source reference, so a failure that's already queued doesn't park, or alert, again.
    2. MGCLatticeIntegrationDlqRetryBatch.run(): the dead-letter retry sweep, which the Lattice dead-letter retry background process runs every 5 minutes when a row is due, replays every Retrying row that is due. When a replay fails and the row's AttemptCount reaches MaxAttempts (5 by default), the row is set to Parked and the event is raised. Until then the row is rescheduled with an exponential backoff (60 seconds, doubling per attempt, capped at one hour).
  • Dependency: retryable failures only reach Parked through the retry sweep, and so only then raise this event. If the Lattice dead-letter retry background process is switched off and no sweep is scheduled in its place, they stay in Retrying and never raise it.
  • Not raised: a manual fix and resubmit from the integration operations console (MGCLatticeIntegrationDlqManager.resubmit()) that fails also sets the row to Parked, but doesn't raise the event; the operator who resubmitted sees the result on screen.
  • Enablement gate: BusinessEventsConfigurationReader::isBusinessEventEnabled(classStr(MGCLatticeIntegrationFailureBusinessEvent)), checked in raiseBusinessEvent() before the event is built, so while the event is not activated, parking an item raises no alert at all. Any exception while raising the event is caught and reported in the infolog so the parking isn't affected; the catch does run, because both callers invoke the alert after their transaction has committed.
protected void raiseBusinessEvent(MGCLatticeIntegrationDeadLetter _deadLetter)
{
try
{
if (BusinessEventsConfigurationReader::isBusinessEventEnabled(classStr(MGCLatticeIntegrationFailureBusinessEvent)))
{
MGCLatticeIntegrationFailureBusinessEvent::newFromDeadLetter(_deadLetter).send();
}
}
catch
{
// Alerting is best-effort and must never break the park path.
error(strFmt("@MGCLattice:DlqAlertBusinessEventFailed", MGCLatticeGuidFormat::toText(_deadLetter.DeadLetterId)));
}
}

Payload Contract​

One row per [DataMember], in declaration order. Sources are the parked MGCLatticeIntegrationDeadLetter row, mapped in initialize(). Each enum is sent as its integer value plus its symbol in a ...Name member.

JSON fieldDisplay labelType / EDTSourceNotes
deadLetterIdDead-letter IDstrMGCLatticeIntegrationDeadLetter.DeadLetterIdIdentifier of the dead-letter row, assigned at enqueue
sourceTypeSource typeintMGCLatticeIntegrationDeadLetter.SourceTypeMGCLatticeIntegrationDlqSource: 1 = AsyncOperation, 2 = FileIngestion
sourceTypeNameSource type namestrSourceType (enum symbol)"AsyncOperation" or "FileIngestion"
serviceNameServicestrMGCLatticeIntegrationDeadLetter.ServiceNameTarget service of the failed item; for file ingestion, the connection ID (empty when the connection couldn't be resolved)
operationNameOperationstrMGCLatticeIntegrationDeadLetter.OperationNameTarget operation; "processOneSegment" for file ingestion
errorCodeError codeintMGCLatticeIntegrationDeadLetter.ErrorCodeMGCLatticeServiceErrorCode value, for example 1 = ValidationFailed, 4 = BusinessRule, 6 = TransientRuntime, 11 = ConfigurationMissing
errorCodeNameError code namestrErrorCode (enum symbol)For example "BusinessRule", "ValidationFailed", "TransientRuntime", "ConfigurationMissing"
statusStatusintMGCLatticeIntegrationDeadLetter.StatusMGCLatticeIntegrationDlqStatus; always 2 (Parked) when this event is raised
statusNameStatus namestrStatus (enum symbol)Always "Parked" when this event is raised
attemptCountAttemptsintMGCLatticeIntegrationDeadLetter.AttemptCount0 when parked at enqueue; equals the row's MaxAttempts when parked by the retry sweep
firstFailedDateTimeFirst failedutcdatetimeMGCLatticeIntegrationDeadLetter.FirstFailedDateTimeUtcWhen the item was first dead-lettered (UTC); \/Date(ms)\/ form
failureMessageFailure messagestrMGCLatticeIntegrationDeadLetter.FailureMessageCut to the first 512 characters

Every Lattice event also carries the Lattice ordering and correlation envelope, inherited from MGCLatticeBusinessEventContractBase: eventSequence (Int64 - increasing across the whole catalog and all companies, allocated when the event is raised; it orders the events of one record, gaps are normal and permanent, see the README), correlationId (String - always Scope:Key; groups emissions that belong to one logical run and defaults to Event: plus a GUID unique to this emission) and schemaVersion (Int - the payload shape version; 1 for this contract). D365 F&O also adds its standard envelope fields to every business event payload: BusinessEventId, BusinessEventLegalEntity, ContextRecordSubject, ControlNumber, EventId, EventTime, EventTimeIso8601, InitiatingUserAADObjectId, MajorVersion, MinorVersion, and ParentContextRecordSubjects. Do not rely on the order of members in the delivered JSON.

This event doesn't call correlateTo, so correlationId is unique to each emission; use deadLetterId to find the item in the integration operations console.

Example Payload​

An asynchronous journal-posting operation that failed and was parked after five retries:

{
"BusinessEventId": "MGCLatticeIntegrationFailureBusinessEvent",
"ControlNumber": 5637150870,
"EventId": "2F6B9D04-E3A7-4C15-8B92-5A0D7E1C6F38",
"EventTime": "\/Date(1790250250000)\/",
"EventTimeIso8601": "2026-09-24T11:44:10.7462213Z",
"MajorVersion": 0,
"MinorVersion": 0,
"BusinessEventLegalEntity": "USMF",
"ContextRecordSubject": "",
"InitiatingUserAADObjectId": "{66AFCCC8-F547-8DAB-C783-430AD85BEA0D}",
"ParentContextRecordSubjects": [],
"eventSequence": 48344,
"correlationId": "Event:9c1e5a27-40b8-4f63-a2d9-e6b03f7c1d84",
"schemaVersion": 1,
"deadLetterId": "5d8a2c71-3e4f-4b90-a6c2-1f7e9b0d3a65",
"sourceType": 1,
"sourceTypeName": "AsyncOperation",
"serviceName": "MGCLatticeGeneralLedgerJournalService",
"operationName": "postGeneralJournal",
"errorCode": 6,
"errorCodeName": "TransientRuntime",
"status": 2,
"statusName": "Parked",
"attemptCount": 5,
"firstFailedDateTime": "\/Date(1790241242000)\/",
"failureMessage": "The operation failed due to an integration runtime error."
}

Activation​

In the D365FO client, go to System administration > Setup > Business events > Business events catalog. Find this event by name ("Integration item parked") or by filtering the Category column to System administration. Select it and use Activate to bind it to a configured endpoint (for example, an Azure Service Bus queue, Event Grid topic, or HTTPS webhook).

There is nothing to schedule: retryable failures park, and raise the event, through the Lattice dead-letter retry background process, which looks for due items every 5 minutes. Keep it enabled on System administration > Setup > Process automations > Background processes. System administration > Periodic tasks > Lattice > Run integration dead-letter retry sweep (menu item MGCLatticeIntegrationDlqRetry) runs the sweep once, now. Parked items are reviewed, replayed, or discarded in System administration > Inquiries > Lattice > Integration operations > Integration operations console.