SMPP Error Codes in A2P SMS: An Operational Guide to Retries, Fixes, and Closures
Learn how to turn SMPP responses, submit_sm errors, and DLRs into operational decisions: retry, fix, investigate, or close, without confusing technical acceptance with handset delivery.

What a submit_sm response confirms—and what it does not
A submit_sm_resp response confirms the result of a request within the SMPP protocol. The command_status field in the response PDU indicates whether the SMSC accepted or rejected that SMPP request and, where applicable, returns an error code.
Technical acceptance is not the same as delivery to the handset. If command_status indicates success and the SMSC returns a message_id, the message has been accepted by that system for subsequent processing. On its own, this does not prove that the message reached the mobile network, was delivered to the device, or was seen by the user.
The first operational rule is to separate acceptance from the arrival of subsequent status evidence. Store the message_id when returned, alongside the internal message identifier, destination, route or connection used, timestamp, and relevant PDU parameters. This correlation may be required to interpret DLRs, query_sm, cancel_sm, or replace_sm.
- Successful submit_sm_resp: the SMPP request was accepted by the SMSC.
- submit_sm_resp with an error: the request failed at that stage and must be classified before resubmission.
- DLR or status query: these provide later information, but must not be confused with independent proof of handset receipt.
- message_id: when returned, a technical reference for later SMPP operations and event correlation.

The SMPP status layers: session, submit acceptance, DLR, and receipt evidence
A reliable operation needs to observe the lifecycle in layers. First comes the session: transport connectivity and bind status. Then comes acceptance or rejection of submit_sm. Later, if requested through registered_delivery and supported by the SMSC, implementation, and agreed connection or route behavior, a delivery receipt may arrive through deliver_sm or data_sm. Not all SMSCs implement both mechanisms, and DLR format and semantics may be provider-specific. Finally, any independent receipt evidence, if it exists for the use case, must be treated as a signal outside SMPP telemetry.
In traditional SMS, independent evidence of receipt at the handset is normally not available through standard SMPP. A DLR is telemetry reported by the SMSC or network; it is not independent proof that the user viewed the message.
SMPP operates over an underlying connection, usually TCP/IP, from which the protocol expects reliable transfer, flow control, and handling of transport errors. A disconnection, timeout, or missing response does not automatically mean that the SMSC did not receive the request. In that case, resending without an application-level correlation and idempotency strategy creates a risk of duplicate submission.
The message_state values defined for query_sm_resp are ENROUTE, DELIVERED, EXPIRED, DELETED, UNDELIVERABLE, ACCEPTED, UNKNOWN, and REJECTED. Retain each status exactly as received, together with the source of the status, observation time, and route context. A later status may change the initial decision made after submit_sm_resp.
- Session: an active connection and a valid bind for the operation type.
- Acceptance: the command_status result in submit_sm_resp.
- Later status: query_sm_resp message_state or a DLR, when available.
- Receipt evidence: if available outside SMPP telemetry, it must not be inferred solely from submit_sm acceptance or a textual DLR format.

Why the same failure does not always require the same action
The action must not depend on the code alone. The same error can have different consequences depending on the destination, affected volume, message criticality, session state, recurrence, and whether recent configuration changes exist. An isolated ESME_RTHROTTLED calls for reduced pressure; a sustained sequence across the entire connection requires reviewing rate control and potentially pausing the flow.
Define a decision matrix that combines four factors: error class, scope, criticality, and available evidence. Classify scope as an individual message, a specific destination, a session, a connection, or a traffic set. Distinguish messages that can functionally expire, such as an OTP, from those that can tolerate delay. Do not amplify a temporary issue with simultaneous retries, and do not turn a data error into repeated retries.
The policy must have explicit limits. Each retry needs a counter, a wait interval, an exit condition, and a mechanism to prevent duplicates when uncertainty lies in the network response. When there is no conclusive response, record the case as uncertain rather than prematurely labeling it rejected or delivered.
- Retry in a controlled way: only when temporary or ambiguous signals justify investigation.
- Correct and resend: when the code indicates incorrect parameters, addressing, credentials, or bind status.
- Pause and escalate: when the failure affects a session, queue, capacity, or significant traffic volume.
- Close: when the issue is permanent, the message loses usefulness, or policy-defined limits are exhausted.
Operational taxonomy of SMPP codes and errors
Practical classification should retain two levels: the exact command_status semantics and an internal operational category. The first level prevents information loss. The second supports automation, alerting, and consistent decisions.
A useful taxonomy separates PDU construction, session and authentication, capacity or throttling, addressing, content or parameter, system errors, and provider-specific extension codes. Not all standard codes resolve the root cause on their own; for example, ESME_RSYSERR is defined only as a system error and does not specify duration, origin, or retryability.
Do not replace the original value with a simplified label. Record the hexadecimal code, SMPP name where available, the PDU involved, sequence_number, command_status, message_id when available, remote system, non-sensitive addressing parameters, and session events close to the failure.
- PDU construction: correct serialization, lengths, fields, and command.
- Session and authentication: restore bind and permissions before sending traffic.
- Capacity: slow down, apply a wait, and monitor recovery.
- Addressing: normalize data and validate the address, TON, and NPI combination.
- System errors and provider-specific extension codes: preserve evidence, limit retries, and request a documented definition when semantics are non-standard.
Session and bind errors: credentials, permissions, bind mode, and connection health
submit_sm can only be issued from a session in the BOUND_TX or BOUND_TRX state. Issuing it from another state may produce ESME_RINVBNDSTS, defined as an incorrect bind state for the command. The correct action is not to immediately resend the same submit: confirm the session state, complete the appropriate bind, and verify that the authorized mode allows transmission.
The errors ESME_RBINDFAIL, ESME_RINVPASWD, and ESME_RINVSYSID correspond to bind failure, invalid password, and invalid system identifier. They should be handled as errors requiring correction. Retrying with the same credentials amplifies failures and may make diagnosis more difficult.
In addition to the code, monitor connection health: socket closures, timeouts, missing responses, frequent reconnections, and unbind events. When a request remains unanswered because of a transport incident, do not assume it was not processed. Before repeating it, apply deduplication controls and, when available and appropriate, query or reconciliation mechanisms based on known identifiers.
- Verify that the session is bound as a transmitter or transceiver before sending submit_sm.
- Check system_id, password, permissions, and bind mode against the authorized configuration.
- Differentiate an explicit SMPP rejection from a timeout or disconnection without a response.
- Do not reschedule uncertain messages in parallel after a transport failure without an anti-duplication strategy.
Temporary errors: congestion, limits, capacity, and controlled waiting
ESME_RTHROTTLED, code 0x00000058, indicates that the ESME has exceeded the allowed message limits. It should be interpreted as a signal to reduce the sending rate. An immediate retry, especially from multiple parallel processes, maintains or worsens the excess that caused the rejection.
ESME_RMSGQFUL, code 0x00000014, indicates a full message queue. Classify it as a capacity signal from the SMSC or route, separate from formatting, credential, or addressing errors. It may be temporary, but the standard does not define a recovery window or guarantee that a retry will succeed.
Apply progressive waiting and a retry limit consistent with the message's usefulness. Reduce concurrency or throughput before retrying. Measure throttling rejections, time to recovery, and scope by connection or destination separately. If errors persist, pause the affected traffic and open an investigation with complete logs.
- ESME_RTHROTTLED: reduce rate, control concurrency, and retry after a wait.
- ESME_RMSGQFUL: treat as a capacity limitation and monitor whether it recovers.
- Avoid simultaneous and unlimited retries.
- Stop retries when the message is no longer useful, the defined maximum is reached, or the incident requires escalation.
- ESME_RSYSERR: investigate first; the standard alone does not allow it to be classified as temporary or retryable.
Permanent or correction-required errors: invalid parameters, addressing, sender, and format
PDU errors require reviewing message construction before a new submission. ESME_RINVMSGLEN indicates an invalid message length; ESME_RINVCMDLEN, an invalid command length; and ESME_RINVCMDID, an invalid command identifier. They are not candidates for an identical retry: serialization or integration logic must be corrected.
In submit_sm, short_message allows up to 254 octets. The specification warns that the exact physical limit may vary according to the underlying network. For longer content, message_payload may be used where supported by the SMSC, subject to its specific rules. Messages may also be segmented across multiple submit_sm PDUs using mechanisms supported by the SMSC or route, such as UDH or SAR TLVs. message_payload and segmentation are interoperability mechanisms subject to implementation support and specific rules; neither mechanism guarantees delivery. Validate the SMSC rules accepted for encoding, segmentation, and other parameters.
ESME_RINVSRCADR and ESME_RINVDSTADR indicate invalid source and destination addresses, respectively. ESME_RINVDSTTON and ESME_RINVDSTNPI also exist for destination TON and NPI. Review the address as a set: value, TON, NPI, and connection acceptance rule. E.164 is an international numbering reference, but an appearance compatible with that reference does not guarantee that the address, TON, NPI, and SMSC policy combination will be accepted.
Apply the same caution to senders: a source address error requires reviewing the transmitted value and associated parameters, as well as the connection rules. Do not try to bypass sender restrictions or messaging policies; correct the configuration and confirm the requirements applicable to the route.
- ESME_RINVMSGLEN, ESME_RINVCMDLEN, and ESME_RINVCMDID: correct the PDU; do not repeat it unchanged.
- ESME_RINVSRCADR and ESME_RINVDSTADR: review the source or destination value.
- ESME_RINVDSTTON and ESME_RINVDSTNPI: review the address, TON, and NPI combination.
- For long messages, follow the documented message_payload or segmentation rules of the integration, SMSC, or route.
- Maintain pre-send validation to reduce avoidable rejections.
Ambiguous or provider-specific errors: preserve evidence and request a documented definition
Not every received code has universal semantics. SMPP reserves ranges for extensions and SMSC providers. If you receive a code outside the standard table, do not reassign it to a generic cause or translate it as failed delivery without documentation. Record the exact value and request a documented technical definition from the remote system.
Delivery receipts also require caution. SMPP allows the SMSC to return a delivery receipt through deliver_sm or data_sm when requested with registered_delivery and supported by the SMSC, implementation, and agreed connection or route behavior. Not all SMSCs implement both mechanisms, and the informative textual content of an SMSC Delivery Receipt is provider-specific. Do not build critical automation based solely on a text string assumed to be universal.
When present, network_error_code represents an actual network error code specific to the technology. Preserve both the network type and code value, in addition to the SMPP status and original DLR text. This evidence enables investigation without removing the distinction between standard SMPP semantics, an SMSC-reported status, and an underlying network code.
A good escalation case includes a timeline, relevant PDU and response, original codes, correlated identifiers, session status, percentage and scope of failures, affected destinations minimized where necessary, and recent configuration changes. Avoid including credentials or unnecessary data.
- Keep command_status in hexadecimal and its standard interpretation where one exists.
- Record DLR text without assuming its format is portable across systems.
- Preserve network_error_code with its network type and original value.
- Request documentation for extension or provider codes.
- Escalate with sufficient technical evidence without exposing connection secrets.
Frequently asked questions
Does a submit_sm_resp with a successful command_status confirm SMS delivery?
No. It confirms that the SMPP request was accepted by the SMSC. Subsequent delivery must be assessed through DLRs, query_sm, or other available evidence, without assuming that acceptance equals receipt at the handset.
What should I do when receiving ESME_RTHROTTLED?
Reduce the sending rate and concurrency, apply a controlled wait, and limit retries. Do not immediately resend in parallel, because the code indicates that allowed limits were exceeded.
What does ESME_RINVBNDSTS mean?
It indicates an incorrect bind state for the command. submit_sm requires a BOUND_TX or BOUND_TRX session. Restore or correct the bind before submitting the message again.
Can I resend a message after an SMPP timeout?
You should do so cautiously. A timeout or disconnection without a response does not prove that the SMSC did not process the request. Apply correlation, deduplication, and reconciliation before resending to reduce the risk of duplicates.
How should I handle an SMPP code specific to a provider?
Keep the original code, the PDU involved, session context, and correlated identifiers. Do not assign standard semantics without supporting documentation. Request a documented technical definition from the provider or remote system.
Does an HLR Lookup confirm that an SMS will be delivered?
No. An HLR Lookup does not prove consent, identity, ownership, or guaranteed delivery. Message acceptance and statuses must be assessed within the messaging flow and according to the limitations of each signal.
Sources consulted
- SMPP Protocol Specification v3.4, Issue 1.2SMPP Developers Forum
- E.164: The international public telecommunication numbering planInternational Telecommunication Union (ITU-T)