A2P SMS Failure Taxonomy: How to Classify Rejections, Expirations, and Uncertain Outcomes
An operational guide to turning HTTP responses, SMPP codes, DLRs, and missing confirmations into comparable, actionable, and traceable categories.

Why a single failed status is not enough to operate a route
A single “failed” status simplifies reporting, but removes the information needed to decide what to do next. An SMPP request rejected because of an invalid destination address is not equivalent to an SMSC accepting a message that later expires during its validity period, or to a system not receiving an interpretable DLR.
An A2P SMS failure taxonomy must make it possible to compare outcomes across routes, providers, destinations, and time windows without replacing the original technical evidence. Its purpose is not to guess the final cause of every message, but to organize observable facts and associate each case with a proportionate action.
A useful classification answers four questions: where the outcome occurred, whether it is final or may evolve, what evidence supports it, and what action is permitted. This discipline reduces unnecessary retries, prevents incorrect attribution, and improves the quality of technical escalations.
- Do not use “failed” as a root cause.
- Keep the request outcome, delivery status, and confirmed cause separate.
- Distinguish final statuses from intermediate statuses.
- Always retain the original code and text received, even after applying an internal mapping.

The evidence principle: observable facts, inferences, and confirmed causes
The first rule is to separate the technical fact from its interpretation. An SMPP response with a successful command_status proves that the protocol operation was accepted; it does not confirm that the SMS reached the handset. Likewise, a DLR with DELIVERED status is a confirmation received through the delivery chain, not an independent and universal verification that a person read the message or physically received it.
DLRs may include an identifier, submission date, completion date, status, and error code. These fields make it possible to reconstruct a lifecycle, provided that the identifier can be reliably associated with the original message. However, the specific format of receipts carried in short_message may vary by gateway or SMSC, so the parser must be controlled by provider or route.
The absence of a DLR does not by itself prove non-delivery either. It may result from a callback not being received, a DLR that could not be interpreted, a reconciliation delay, or an upstream reporting policy. It should be classified as uncertainty until additional evidence is available.
- Observable fact: HTTP response, submit_sm_resp, DLR, callback, status query, or internal timeout.
- Inference: “probable congestion,” “possible sender restriction,” or “possible filtering.”
- Confirmed cause: only when a code, documented response, or provider investigation identifies it.
- Confidence level: record whether the classification is direct, inferred, or awaiting confirmation.

The five operational outcome families
A minimum, comparable taxonomy can organize outcomes into five families. Each family should retain the original status, the source of evidence, and the confidence level. The families do not replace provider codes: they group them for operational, analytical, and decision-making purposes.
The same route can produce outcomes from several families. For this reason, a route should not be judged using a single aggregate percentage without reviewing failure composition, trends over time, and the evidence available.
- Pre-acceptance rejection: the local platform aborts the attempt before reaching the SMSC, or the SMSC rejects the request. Keep these two situations distinct. Possible technical examples include bind failure, invalid credentials, invalid source address, or invalid destination address.
- Temporary failure: provider evidence explicitly identifies it as temporary or retryable. Do not turn a generic error into a temporary one for operational convenience.
- Final failure: there is a final negative outcome for which the documentation or available evidence does not indicate a safe retry. An SMSC rejection may belong to this family when it is likely to recur with the same request.
- Expiration: the message exhausted its validity window before delivery was completed. It should be separated from final failure because the validity duration and use case are relevant.
- Uncertain outcome: the SMSC may have accepted the message, but there is no received and interpretable DLR that can close it as delivered, failed, or expired.
Data to retain for each message
Classification will be weak if records do not make it possible to reconstruct the sequence. The internal identifier must coexist with identifiers assigned by the platform, provider, or SMSC. The DLR must be linked to the original message without relying only on receipt text that may vary across implementations.
The destination should be stored in a normalized international format in line with the E.164 numbering plan structure, separate from attributes used for routing or segmentation. Normalization does not make a number valid, active, consented, or deliverable; it only improves data-handling and analysis consistency.
It is also important to retain a controlled classification of content and sender, without using those fields to infer a cause without evidence. For example, a behavioral difference by sender type may justify an investigation, but does not by itself confirm a sender restriction.
- Internal identifier for the attempt and the logical message.
- Platform, provider, SMSC, and DLR identifiers where available.
- Timestamps: creation, acceptance, submission, update, DLR receipt, and internal closure.
- Normalized destination, associated country, and operator only when the data exists with sufficient evidence.
- Sender, sender type, and relevant request configuration.
- Route, provider, connection, parser version, and mapping version.
- Content class or use case: OTP, transactional, or legitimate marketing.
- Original status and code, original text, normalized family, confidence level, and next action.
How to map HTTP, SMPP, and DLRs without losing information
Mapping should be an additional, reversible layer. Store the original response first, then apply a versioned rule that produces an operational category. Do not overwrite an SMPP code, HTTP status, or DLR text with an internal label such as “invalid number” or “filtered” if that cause has not been confirmed.
In SMPP, command_status indicates the success or failure of an SMPP request. Codes such as ESME_RINVSRCADR, ESME_RINVDSTADR, ESME_RSYSERR, ESME_RBINDFAIL, and ESME_RINVPASWD have distinct technical meanings and must remain available for diagnosis. A successful submit_sm response must not be mapped to “delivered”: at most, it should be mapped to “accepted by the protocol operation” or an equivalent intermediate status.
Delivery statuses also require a temporal hierarchy. ENROUTE is intermediate and may evolve, for example, into DELIVERED or EXPIRED. A parser must not close a message irreversibly while it only has a status that can still change.
- Capture the protocol, endpoint or command, code, text, original payload, and receipt timestamp.
- Apply a rule with a version, scope, and effective date.
- Define update precedence: a valid final DLR must take precedence over an earlier intermediate status.
- Keep non-interpretable DLRs in a review queue and temporarily classify them as an uncertain outcome.
- Version parsers by provider, connection, or route when the receipt format requires it.
- Avoid programmatically relying on changing texts from specific errors; use them as retained diagnostic evidence.
Classification by actionability
The usefulness of a taxonomy is demonstrated when it guides safe actions. Not every category authorizes a retry, and not every incident requires stopping traffic. The action should depend on the family, the original code, the use case, the validity window, and the accumulated evidence.
Decisions should be executed through explicit rules. A retry may be appropriate when the provider identifies the outcome as temporary or retryable; it should not be applied automatically to rejections likely to produce the same error with the same request. If uncertainty exists, reconcile the status before creating duplicates.
- Correct data or configuration: apply this to evidence such as an invalid destination, invalid sender, bind error, or incorrect credentials. Validate before resending.
- Retry safely: only with evidence of temporariness or retryability, a deduplication policy, and a validity window that is still useful.
- Stop or limit traffic: when there are sustained increases in technical rejections, authentication failures, system errors, or behavioral changes affecting a route. The measure should be reviewed with data, not through automatic attribution.
- Escalate to the provider: when there are persistent codes, inconsistent DLRs, non-interpretable receipts, identifier discrepancies, or growing uncertain outcomes.
- Keep under observation and reconcile: for intermediate statuses, missing DLRs within the defined window, or conflicts between status sources.
Ambiguous errors: when to use “cause undetermined”
A “cause undetermined” category is necessary when the evidence does not allow a specific cause to be identified. It is not an analytical failure: it prevents a hypothesis from becoming operational data. It should be used, for example, when a generic non-delivery status is received without a code that distinguishes among possible causes.
Do not automatically attribute non-delivery to content filtering, handset unavailability, sender restriction, congestion, or numbering issues. A negative status may cover several causes. Attribution should wait for a specific code, a documented provider response, consistent evidence by segment, or a confirmed investigation.
For this category to be useful, it must not become a permanent catch-all. Each case should retain enough metadata to be reclassified if a late DLR arrives, the parser is updated, or the provider provides clarification.
- Use “cause undetermined” when discriminating evidence is missing.
- Do not use this category to hide parser errors, lost callbacks, or missing correlation: record those issues separately.
- Measure its proportion by route, provider, destination, and integration version.
- Open a review if it rises consistently or becomes concentrated on the same route or DLR format.
- Reclassify only through a versioned rule and retain the change history.
Different rules for OTP, transactional, and legitimate marketing
The failure category does not change by use case, but the action may change. An OTP has limited usefulness over time and requires particular care with retries: sending a duplicate or delayed code can confuse the recipient and may not resolve access. The system must respect code validity and avoid retries when they no longer provide value.
Transactional messages may support a different retry policy if their content remains valid and the event is not duplicated in a harmful way. Legitimate marketing requires even greater discipline: it should only be sent to recipients with the applicable legal basis and permissions, and an uncertain outcome must not be used to justify repeated resends.
The validity period is part of the decision. Expiration indicates that the message remained pending until a configured window was exhausted before failing at the platform. Therefore, analyze expirations together with configured validity, rather than only as a route-quality indicator.
- OTP: close quickly, use strict deduplication, and retry only if still within code validity and policy permits it.
- Transactional: validate idempotency, event validity, and duplication risk before retrying.
- Legitimate marketing: limit frequency, respect applicable consent and exclusions, and do not use uncertainty as a reason to persist.
- For all use cases: document the retry policy, maximum number of attempts, and closure condition.
Frequently asked questions
Does a successful submit_sm_resp response confirm SMS delivery?
No. It confirms the successful outcome of the SMPP request to the message center or responding platform. Delivery requires subsequent evidence, such as a DLR or equivalent delivery status.
Does the absence of a DLR mean the SMS was not delivered?
Not necessarily. The callback may not have been received, the DLR may not have been interpretable, or an update may still be pending. Classify the case as an uncertain outcome, check the message record after a defined window, and reconcile regularly.
Should all A2P SMS failures be retried?
No. Retry only when provider evidence indicates temporariness or retryability and when the use case, validity, and deduplication rules allow it. Retrying a rejection that is likely to recur can increase useless traffic and hide a configuration issue.
Can an undelivered status prove content filtering?
Not by itself. A generic non-delivery status may have different causes, including circumstances related to content or handset availability. A code, documented response, or additional evidence is needed to attribute a specific cause.
What is the difference between expiration and final failure?
Expiration means that a validity window was exhausted before delivery was completed. A final failure is a definitive negative outcome that is not classified as expiration. Keeping them separate makes it possible to review the validity policy and make better retry decisions.
What is the value of retaining original codes if an internal category already exists?
Original codes preserve technical evidence and support auditing, troubleshooting, and mapping updates. The internal category makes comparative analysis easier, but should not erase the meaning of the protocol, provider, or received DLR.
Sources consulted
- SMPP Protocol Specification v3.4, Issue 1.2SMPP Developers Forum
- SMPP Delivery Receipt FormatSMPP Developers Forum
- Retrieve a delivery reportSinch
- Best Practices for Messaging Delivery Status LoggingTwilio
- Messages resourceTwilio
- Outbound Message Status in Status CallbacksTwilio
- Recommendation ITU-T E.164 (02/2026): The international public telecommunication numbering planInternational Telecommunication Union