The short answer
SMPP has two kinds of status. The command_status in each response tells you whether the SMSC accepted your request. 0x00000000 means yes; anything else is an error from the table below.
The delivery receipt comes later. It tells you whether the message reached the phone, with a final state such as DELIVRD, UNDELIV or EXPIRED.
An accepted submit_sm is not a delivered message. Always read the receipt as well.
Where codes appear
- Response PDUs. Every response, such as
bind_transceiver_resporsubmit_sm_resp, carries acommand_statusin its header. Requests set it to NULL. generic_nack. The SMSC sends this when a PDU has an invalidcommand_lengthor an unknowncommand_id. Itscommand_statusgives the reason.submit_multi_resp. Each failed destination carries its ownerror_status_code, using the same values.- Delivery receipts. A
deliver_smwithesm_classbits 5 to 2 set to 0001 carries a receipt. Its state is in themessage_stateoptional parameter and in thestat:text.
Codes are 4-byte integers. Some libraries log them in decimal, so 0x00000058 may show as 88. The filter below accepts both.
command_status codes
All error codes defined in SMPP 3.4, Table 5-2, with the spec's description and a practical fix.
Showing all 48 codes.
| Code | Dec | Name | Meaning (spec) | What to do |
|---|---|---|---|---|
0x00000000 | 0 | ESME_ROK | No Error | Success. Nothing to fix. |
0x00000001 | 1 | ESME_RINVMSGLEN | Message Length is invalid | Check that sm_length matches short_message. Keep short_message to 140 bytes, or split the text into parts. |
0x00000002 | 2 | ESME_RINVCMDLEN | Command Length is invalid | The PDU header length does not match the PDU. Check how your client encodes PDUs and log the raw bytes. |
0x00000003 | 3 | ESME_RINVCMDID | Invalid Command ID | The SMSC does not know this command. Use SMPP 3.4 commands and check the version your library binds with. |
0x00000004 | 4 | ESME_RINVBNDSTS | Incorrect BIND Status for given command | The command is not allowed in your bind state, such as submit_sm on a receiver bind. Bind as transceiver or transmitter to send. |
0x00000005 | 5 | ESME_RALYBND | ESME Already in Bound State | Already bound: don't bind twice on one connection. |
0x00000006 | 6 | ESME_RINVPRTFLG | Invalid Priority Flag | Use a priority_flag from 0 to 3. Values above 3 are reserved. |
0x00000007 | 7 | ESME_RINVREGDLVFLG | Invalid Registered Delivery Flag | Use registered_delivery 1 for a receipt on success or failure, or 0 for no receipt. |
0x00000008 | 8 | ESME_RSYSERR | System Error | A fault on the SMSC side. Retry later, waiting longer after each try. If it continues, contact your provider with the time and sequence_number. |
0x0000000A | 10 | ESME_RINVSRCADR | Invalid Source Address | Sender ID not valid: use an active sender ID and the right TON and NPI. |
0x0000000B | 11 | ESME_RINVDSTADR | Invalid Dest Addr | Recipient number not valid: use the country code followed by the number. |
0x0000000C | 12 | ESME_RINVMSGID | Message ID is invalid | Use the exact message_id from submit_sm_resp in query_sm, cancel_sm or replace_sm. |
0x0000000D | 13 | ESME_RBINDFAIL | Bind Failed | Bind failed: check the connection limit and allowed IPs on your SMPP app. |
0x0000000E | 14 | ESME_RINVPASWD | Invalid Password | Wrong password. Use the password of your SMPP app. |
0x0000000F | 15 | ESME_RINVSYSID | Invalid System ID | Wrong system ID. Use the system ID of your SMPP app. |
0x00000011 | 17 | ESME_RCANCELFAIL | Cancel SM Failed | Only messages still pending delivery can be cancelled. Check the message_id and that the source address matches the original. |
0x00000013 | 19 | ESME_RREPLACEFAIL | Replace SM Failed | Only a message still pending delivery can be replaced. Check the message_id and that the source address matches the original. |
0x00000014 | 20 | ESME_RMSGQFUL | Message Queue Full | Queue full: pause and retry later. |
0x00000015 | 21 | ESME_RINVSERTYP | Invalid Service Type | Leave service_type empty (NULL) for the default, unless your provider gave you a value. |
0x00000033 | 51 | ESME_RINVNUMDESTS | Invalid number of destinations | In submit_multi, set number_of_dests to the number of addresses you send. The maximum is 254. |
0x00000034 | 52 | ESME_RINVDLNAME | Invalid Distribution List name | The SMSC does not know this list name. Send to phone numbers instead (dest_flag 1). |
0x00000040 | 64 | ESME_RINVDESTFLAG | Destination flag is invalid (submit_multi) | Set dest_flag to 1 for a phone number or 2 for a distribution list name. |
0x00000042 | 66 | ESME_RINVSUBREP | Invalid 'submit with replace' request (i.e. submit_sm with replace_if_present_flag set) | Set replace_if_present_flag to 0 unless your provider supports replace. |
0x00000043 | 67 | ESME_RINVESMCLASS | Invalid esm_class field data | Use esm_class 0x00 for a single SMS, and 0x40 when short_message starts with a concatenation header. |
0x00000044 | 68 | ESME_RCNTSUBDL | Cannot Submit to Distribution List | Send to individual phone numbers instead. |
0x00000045 | 69 | ESME_RSUBMITFAIL | submit_sm or submit_multi failed | Submit failed: check the fields and your balance, then retry. |
0x00000048 | 72 | ESME_RINVSRCTON | Invalid Source address TON | Use source_addr_ton 5 for a name such as YOURBRAND, or 1 for a number. |
0x00000049 | 73 | ESME_RINVSRCNPI | Invalid Source address NPI | Use source_addr_npi 0 for a name, or 1 for a number. |
0x00000050 | 80 | ESME_RINVDSTTON | Invalid Destination address TON | Use dest_addr_ton 1 (international). |
0x00000051 | 81 | ESME_RINVDSTNPI | Invalid Destination address NPI | Use dest_addr_npi 1 (E.164). |
0x00000053 | 83 | ESME_RINVSYSTYP | Invalid system_type field | Set system_type in your bind to NULL, unless your provider gave you a value. |
0x00000054 | 84 | ESME_RINVREPFLAG | Invalid replace_if_present flag | Use 0 (don't replace) or 1 (replace). Values 2 to 255 are reserved. |
0x00000055 | 85 | ESME_RINVNUMMSGS | Invalid number of messages | The SMSC rejected a message count in your request. Check any count field you set. |
0x00000058 | 88 | ESME_RTHROTTLED | Throttling error (ESME has exceeded allowed message limits) | Over your throughput: slow down and retry later. |
0x00000061 | 97 | ESME_RINVSCHED | Invalid Scheduled Delivery Time | Send schedule_delivery_time as NULL for immediate delivery, or in the 16-character format YYMMDDhhmmsstnnp. |
0x00000062 | 98 | ESME_RINVEXPIRY | Invalid message validity period (Expiry time) | Send validity_period as NULL for the SMSC default, or in the 16-character time format. The SMSC may cap how far ahead it can be. |
0x00000063 | 99 | ESME_RINVDFTMSGID | Predefined Message Invalid or Not Found | Set sm_default_msg_id to NULL (0) unless you send a message stored on the SMSC. |
0x00000064 | 100 | ESME_RX_T_APPN | ESME Receiver Temporary App Error Code | A receiving application reports a temporary error. Your system can return it in deliver_sm_resp when it cannot take a message for now. |
0x00000065 | 101 | ESME_RX_P_APPN | ESME Receiver Permanent App Error Code | A receiving application reports a permanent error. Do not resend the same message unchanged. |
0x00000066 | 102 | ESME_RX_R_APPN | ESME Receiver Reject Message Error Code | A receiving application rejected this message. Do not resend it unchanged. |
0x00000067 | 103 | ESME_RQUERYFAIL | query_sm request failed | Check the message_id and that the source address matches the original message. |
0x000000C0 | 192 | ESME_RINVOPTPARSTREAM | Error in the optional part of the PDU Body. | The optional parameters (TLVs) are malformed. Check the tag, length and value of each one your client adds. |
0x000000C1 | 193 | ESME_ROPTPARNOTALLWD | Optional Parameter not allowed | Remove optional parameters this PDU does not allow or the SMSC does not support. |
0x000000C2 | 194 | ESME_RINVPARLEN | Invalid Parameter Length. | A field is too long or too short. Check sizes against the spec, such as at most 21 octets for destination_addr. |
0x000000C3 | 195 | ESME_RMISSINGOPTPARAM | Expected Optional Parameter missing | Add the optional parameter the SMSC expects. Ask your provider which one. |
0x000000C4 | 196 | ESME_RINVOPTPARAMVAL | Invalid Optional Parameter Value | An optional parameter has a value the SMSC does not accept. Check the value against the spec. |
0x000000FE | 254 | ESME_RDELIVERYFAILURE | Delivery Failure (used for data_sm_resp) | Read delivery_failure_reason and network_error_code in the data_sm_resp. Used in transaction mode only. |
0x000000FF | 255 | ESME_RUNKNOWNERR | Unknown Error | Retry later, waiting longer after each try. If it repeats, contact your provider with the time and the PDU. |
No defined code matches. Try the last digits, such as 58, or part of the name, such as BIND. Codes not listed here are in the reserved and vendor ranges.
Source: SMPP Protocol Specification v3.4, Issue 1.2 (SMPP Developers Forum), section 5.1.3, Table 5-2. Checked 6 November 2026.
Reserved and vendor ranges
SMPP 3.4 reserves the gaps between the codes above, and sets aside one range for each SMSC vendor's own errors.
| Value or range | Spec says | What to do |
|---|---|---|
0x00000009 | Reserved | Not defined in SMPP 3.4. Log the full PDU and ask your provider what it means. |
0x00000010 | Reserved | Not defined in SMPP 3.4. Log the full PDU and ask your provider what it means. |
0x00000012 | Reserved | Not defined in SMPP 3.4. Log the full PDU and ask your provider what it means. |
0x00000016 to 0x00000032 | Reserved | Not defined in SMPP 3.4. Log the full PDU and ask your provider what it means. |
0x00000035 to 0x0000003F | Reserved | Not defined in SMPP 3.4. Log the full PDU and ask your provider what it means. |
0x00000041 | Reserved | Not defined in SMPP 3.4. Log the full PDU and ask your provider what it means. |
0x00000046 to 0x00000047 | Reserved | Not defined in SMPP 3.4. Log the full PDU and ask your provider what it means. |
0x00000052 | Reserved | Not defined in SMPP 3.4. Log the full PDU and ask your provider what it means. |
0x00000056 to 0x00000057 | Reserved | Not defined in SMPP 3.4. Log the full PDU and ask your provider what it means. |
0x00000059 to 0x00000060 | Reserved | Not defined in SMPP 3.4. Log the full PDU and ask your provider what it means. |
0x00000068 to 0x000000BF | Reserved | Not defined in SMPP 3.4. Log the full PDU and ask your provider what it means. |
0x000000C5 to 0x000000FD | Reserved | Not defined in SMPP 3.4. Log the full PDU and ask your provider what it means. |
0x00000100 to 0x000003FF | Reserved for SMPP extension | Later versions use this range: SMPP 5.0 defines codes such as 0x00000104 (ESME_RINVDCS, invalid data coding). Check which SMPP version your provider speaks. |
0x00000400 to 0x000004FF | Reserved for SMSC vendor specific errors | The meaning depends on the SMSC. Ask your provider for their list. |
0x00000500 to 0xFFFFFFFF | Reserved | Not defined in SMPP 3.4. Log the full PDU and ask your provider what it means. |
Source: SMPP Protocol Specification v3.4, Issue 1.2 (SMPP Developers Forum), section 5.1.3, Table 5-2. Checked 6 November 2026.
message_state values
The SMSC reports a message's state as a number in query_sm_resp, and in the message_state optional parameter of a delivery receipt. The receipt text uses a 7-letter short form.
| Value | State | stat: text | Meaning (spec) | What it usually means for you |
|---|---|---|---|---|
1 | ENROUTE | Not a final state | The message is in enroute state. | Still being delivered. Wait for the final state. |
2 | DELIVERED | DELIVRD | Message is delivered to destination | Delivered to the phone. No action needed. |
3 | EXPIRED | EXPIRED | Message validity period has expired. | Not delivered in time, for example because the phone stayed off. Resend only if the message still matters. |
4 | DELETED | DELETED | Message has been deleted. | Deleted on the SMSC, so it will not be delivered. |
5 | UNDELIVERABLE | UNDELIV | Message is undeliverable | The network could not deliver it, for example to an unreachable number. Check the number before you resend. |
6 | ACCEPTED | ACCEPTD | Message is in accepted state (i.e. has been manually read on behalf of the subscriber by customer service) | Read on the subscriber's behalf by customer service. Treat it as a final state. |
7 | UNKNOWN | UNKNOWN | Message is in invalid state | The final state is not known. Do not count it as delivered. |
8 | REJECTED | REJECTD | Message is in a rejected state | Refused before delivery. Check the sender ID, number and content before you resend. |
Source: SMPP Protocol Specification v3.4, Issue 1.2 (SMPP Developers Forum), section 5.2.28, Table 5-6, and Appendix B, Table B-2. Checked 6 November 2026.
Delivery receipt format
Ask for a receipt by setting registered_delivery to 1 in submit_sm. Value 2 asks for a receipt only when delivery fails. The receipt arrives as a deliver_sm, and its text is in short_message.
SMPP 3.4 says the receipt format is SMSC vendor specific, and gives this typical example:
id:IIIIIIIIII sub:SSS dlvrd:DDD submit date:YYMMDDhhmm done date:YYMMDDhhmm stat:DDDDDDD err:E Text: . . .
| Field | Size in spec | What it holds |
|---|---|---|
id | 10 | The message ID the SMSC gave the message when you submitted it. |
sub | 3 | Number of messages originally submitted. Only relevant for distribution lists. Padded with leading zeros. |
dlvrd | 3 | Number of messages delivered. Only relevant for distribution lists. Padded with leading zeros. |
submit date | 10 | When the message was submitted, as YYMMDDhhmm. |
done date | 10 | When the message reached its final state, as YYMMDDhhmm. |
stat | 7 | The final state, such as DELIVRD. See message_state values. |
err | 3 | Where appropriate, a network or SMSC error code. See The err: field. |
text | 20 | The first 20 characters of the message. |
Source: SMPP Protocol Specification v3.4, Issue 1.2 (SMPP Developers Forum), Appendix B, Table B-1. Checked 6 November 2026.
A receipt from Unecast looks like this, as shown in the SMS API reference:
id:MESSAGE_ID sub:001 dlvrd:001 submit date:2611051030 done date:2611051030 stat:DELIVRD err:000 text:Your OTP is 482913
- Match receipts by ID. The
receipted_message_idoptional parameter holds the ID from yoursubmit_sm_resp. Prefer it to parsingid:from the text. - Parse by key, not by position. The format is vendor specific, so field sizes and letter case can differ.
- Always answer. Reply to every
deliver_smwith adeliver_sm_resp, or the receipt may be sent again.
The err: field
SMPP 3.4 does not define the values of err:. The spec says it may hold a network specific error code or an SMSC error code, and that these errors are network or SMSC specific.
So the same err: number can mean different things on different routes. Read stat: first for the outcome, and use err: only with your provider's own list.
A receipt may also carry the network_error_code optional parameter. Its first byte names the network type (3 is GSM) and the next two bytes hold the network's error code.
Source: SMPP Protocol Specification v3.4, Issue 1.2 (SMPP Developers Forum), Appendix B, Table B-1, and section 5.3.2.31. Checked 6 November 2026.
Unecast SMPP
The Unecast SMSC speaks standard SMPP 3.4, so the codes and states on this page apply. Connect to smpp://smsc.unecast.com:2775 with the system ID and password of an SMPP app from the SMS portal.
- Bind:
bind_transceiversends messages and receives receipts on one connection. - Receipts: set
registered_deliveryto 1. - Keep alive: send
enquire_linkabout every 30 seconds when the link is idle. - Slow down when asked: on
0x00000058or0x00000014, pause and retry that message later.
Settings, submit_sm fields and a Python example are in the SMS API reference. For err: values you see on Unecast receipts, ask our engineers.
Frequently asked questions
What does SMPP error 0x00000058 mean?
0x00000058 is ESME_RTHROTTLED: you sent faster than the SMSC allows. Slow down, pause, and retry that message later. Libraries that print decimals show it as 88.
What is the difference between command_status and a delivery receipt?
command_status is in every response PDU, such as submit_sm_resp, and tells you whether the SMSC accepted your request. A delivery receipt arrives later as a deliver_sm and reports what happened to the message on the network, in its stat: field.
What does stat:UNDELIV mean in a delivery receipt?
UNDELIV is the short form of the UNDELIVERABLE message state (5): the message could not be delivered, for example to an unreachable number.
What do the err: codes in a delivery receipt mean?
SMPP 3.4 does not define them. The err: field may hold a network or SMSC error code, and these are network or SMSC specific. Ask your provider for their list.
Why am I not getting delivery receipts?
Set registered_delivery to 1 in submit_sm, bind as a transceiver or receiver, and answer every deliver_sm with a deliver_sm_resp. Receipts arrive as deliver_sm, which an SMSC only sends on a receiver or transceiver bind.
Which SMPP error codes should I retry?
Retry later on throttling (0x00000058), queue full (0x00000014) and system errors (0x00000008), waiting longer after each try. Do not retry bind, address or field errors until you fix the request.