Intermittent ErrorItemNotFound on message/attachment GET after change notifications (async) #3142
Replies: 1 comment
-
|
Yes, under default Microsoft Graph behavior, both Why default IDs are unstableAccording to the Microsoft Graph message resource behavior, the message ID can change when an item is moved between containers (for example, Inbox → subfolder via a rule). A move operation effectively creates a new message instance, which results in a new message ID and new attachment IDs. This is why a notification can reference a message ID that no longer exists by the time your worker tries to fetch it. Common causes in async pipelinesOne frequent cause is folder movement occurring between the time a change notification is generated and the time your Lambda processes it. Email rules, junk filtering, or backend processing can move the message immediately after delivery, causing the original ID to become invalid. Another common issue is replication delay. The notification can fire before the message is fully available across all stores, which leads to transient Attachment IDs are even less stable. They are scoped to the specific message instance. If the message is reprocessed, rescanned, or modified by services such as Safe Attachments scanning, the attachment collection can be reconstructed, resulting in different attachment IDs than what was previously returned. Why Graph Explorer and production differGraph Explorer typically queries the current state of the item at request time. In contrast, your pipeline is working off previously received notification data, which may already be stale due to folder moves or replication timing. It is also possible that one path uses default IDs while another uses immutable IDs, which leads to inconsistencies in observed behavior. Recommended approach for async processingThe correct approach is to treat notification payloads as pointers, not durable identifiers. Always re-fetch the message using the ID from the notification and treat failures as retryable. If Attachment IDs should never be persisted across processing steps. Instead, always re-list attachments at the time of processing and immediately download them using the IDs returned from that fresh enumeration. Use immutable IDs for stabilityTo reduce instability, enable immutable ID mode by using the Immutable IDs remain stable across folder moves within the same mailbox, which significantly reduces this class of issue. However, they do not protect against mailbox migration or export/import scenarios. Recommended headers and usage patternAll message and attachment operations should consistently include: Prefer: IdType="ImmutableId" This ensures consistent identifier behavior across your read paths. Reliable deduplication strategyFor long-running workflows, do not rely on Graph message IDs alone. Instead, use You can also re-resolve messages using: GET /users/{user}/messages?$filter=internetMessageId eq '' This is more reliable for recovery scenarios than storing transient Graph IDs. Handling duplicate notificationsIt is normal to receive multiple change notifications for the same logical email with different message IDs due to folder moves or intermediate processing states. Idempotency should be based on a combination of mailbox and Key takeawayDefault Graph IDs are only safe for immediate retrieval. They are not safe for async workflows without re-validation. Immutable IDs improve stability significantly, but the correct architectural pattern is still: treat notifications as triggers, re-fetch state, and never persist attachment IDs across steps. This behavior is documented but often surprises implementers because Explorer queries mask the timing and replication effects seen in production pipelines. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
We use Microsoft Graph to read Outlook messages and attachments in an async integration (processing runs after Microsoft Graph change notifications, e.g. AWS Lambda / SQS).
We resolve the message and attachments roughly like this:
Equivalent REST calls:
The issue is
We obtain messageId (and attachmentId when listing attachments) from Graph during processing.
Intermittently, a later GET returns ErrorItemNotFound for that same id.
The same request may succeed in Graph Explorer or on retry after a delay, which does not match stable “store this id forever” behavior for async jobs.
Additionally: a customer may copy an attachment id from Graph Explorer, but CloudWatch logs for our pipeline often show a different attachment id (or no attachment id) for the same message — messageId may align, attachmentId may not — so we cannot reconcile Explorer vs our logs.
Expected behavior
messageId and attachmentId returned by Graph should remain valid for GET for long enough or Microsoft should document when ids can change and what async integrators must persist instead (e.g. refetch, internetMessageId, or other supported pattern).
How to reproduce
Intermittent.
References (optional)
Stack Overflow: MS Graph message API attachment id changed
Stack Overflow: Item ids and attachment ids that change
SDK Version
Microsoft.Graph: 5.5.6/5.5.7
Additional context regarding our scenario:
We receive Microsoft Graph push notifications for incoming emails and use the messageId received in the notification to make subsequent Graph API calls to fetch the email details and attachments.
Since our processing is asynchronous, we rely on the messageId and attachmentId returned by Microsoft Graph. However, we are intermittently seeing cases where these IDs appear to change or become invalid, resulting in ErrorItemNotFound.
Could you please clarify whether message IDs or attachment IDs are expected to change under certain scenarios? If so, what is the recommended alternative approach or identifier that should be used by integrations that process emails based on Graph change notifications?
Beta Was this translation helpful? Give feedback.
All reactions