> For the complete documentation index, see [llms.txt](https://docs.verifone.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.verifone.com/psdk-latest/reference-material/code-labs/error-handling.md).

# Error Handling

{% columns %}
{% column width="41.66666666666667%" %} <i class="fa-clock">:clock:</i> 6 minutes reading time\ <i class="fa-calendar">:calendar:</i> Last updated: 10th October, 2025
{% endcolumn %}

{% column width="24.999999999999986%" %}

{% endcolumn %}

{% column %}

{% endcolumn %}
{% endcolumns %}

{% stepper %}
{% step %}
Status and its Subclasses

All of the events are derived from Status, and most methods return a Status object, with only a few exceptions. In these scenarios, if the status code ([Status.getStatus()](https://docs.verifone.com/psdk-api-latest/android-java/index/status#getstatus)) returns non-zero, an error has occurred. In most cases, [Status.getMessage()](https://docs.verifone.com/psdk-api-latest/android-java/index/status#getmessage) returns a localized, human-readable message that can be displayed to the cashier if the error cannot be automatically handled. In some cases, the status code will be assigned some constant value that can be automatically handled, such as those defined in CommerceConstants or in the appropriate Status subclass for the event type, but some will not. In the cases where it is not found, it can be helpful to try again depending on the context. See [PSDK State Transitions](/psdk-latest/psdk-user-guide-and-training/psdk-user-guide/pos_guide.md#psdk-state-transitions).
{% endstep %}

{% step %}
When the status code is non-zero after calling a method

Many methods, such as [TransactionManager.login()](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionmanager#loginwithcredentials-logincredentials), return a Status object. Check this status object for a non-zero status code after calling to make sure that the login request could be submitted. An error when calling a method is generally due to some unready state or invalid parameter. Invalid parameters should be caught during development/testing and should not be present in the field. An unready state can happen if the POI has not fully booted, such as after a recent restart of the device, and will generally require some delay before attempting the action.

Most of these errors that occur in the field can be handled by displaying [Status.getMessage()](https://docs.verifone.com/psdk-api-latest/android-java/index/status#getmessage) to the cashier and enabling them to retry or cancel the action. If they cancel, it is the responsibility of the POS to restore the correct state, e.g., if some merchandise failed to add to the POI display, the merchandise should probably be removed from the cart so the display and the cart can be kept in sync.
{% endstep %}

{% step %}
When the status code is non-zero for a received event

It is possible for any of the events to be sent to the listener with an error. When an error has occurred, the event might not contain any of the expected objects, e.g., a [PaymentCompletedEvent ](https://docs.verifone.com/psdk-api-latest/android-java/index/paymentcompletedevent)might return null for [PaymentCompletedEvent.getPayment()](https://docs.verifone.com/psdk-api-latest/android-java/index/paymentcompletedevent#getpayment). Depending on the exact event, these errors should be handled differently and really depend on the product requirements and paradigms in the POS.

**Note:** A payment card decline or user-canceled payment is not considered an error since it is a normally expected authorization result; therefore, the status code will be 0 in this case. In payment cases, an error could be returned if the card was invalid, or the payment host returned an error, or many other scenarios. In this case, the status code will be one specific to the host or payment app, and should be included in the display to the cashier to help them if they reach out for support.
{% endstep %}

{% step %}
StatusInformation structure

Along with Status, PSDK is providing a [StatusInformation](https://docs.verifone.com/psdk-api-latest/android-java/index/statusinformation) structure, which provides a wider range of error codes of integer type. Every Event provides `getStatusInformation()` method to return this structure. The codes are compartmentalized into layered categories of [StatusType](https://docs.verifone.com/psdk-api-latest/android-java/index/statustype). [StatusInformation](https://docs.verifone.com/psdk-api-latest/android-java/index/statusinformation) provides `result_code` value and type value. The retrieved type is providing information on which error code structure ([PsdkInternalStatus](https://docs.verifone.com/psdk-api-latest/android-java/index/psdkinternalstatus), [CommunicationStatus](https://docs.verifone.com/psdk-api-latest/android-java/index/communicationstatus), [InitializationStatus](https://docs.verifone.com/psdk-api-latest/android-java/index/initializationstatus), [CommandStatus](https://docs.verifone.com/psdk-api-latest/android-java/index/commandstatus), [TransactionStatus](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionstatus), [TransactionDeclinedErrors](https://docs.verifone.com/psdk-api-latest/android-java/index/transactiondeclinederrors), and [SuccessStatus](https://docs.verifone.com/psdk-api-latest/android-java/index/successstatus)) to compare the `result_code` against to get the error code meaning. The [StatusType](https://docs.verifone.com/psdk-api-latest/android-java/index/statustype) is layered in the sense that an error of, for example, COMMAND\_STATUS layer implies that layers below (COMMUNICATION\_STATUS, INITIALIZATION\_STATUS, PSDK\_INTERNAL\_STATUS did not produce an error during execution, and the execution flow did not reach layers above (TRANSACTION\_STATUS, TRANSACTION\_DECLINED\_ERRORS, SUCCESS\_STATUS). Detailed descriptions of each of the `result_code` values are available within API reference.

```java

// Listener receives the PaymentCompletedEvent.
@Override // Overridden from the CommerceListenerAdapter
public void handlePaymentCompletedEvent(PaymentCompletedEvent event) {
    if (TransactionEvent.TRANSACTION_PAYMENT_COMPLETED.equals(event.getType())) {
        StatusInformation statusInfo = event.getStatusInformation();
        Log.d(TAG, "Received Status Information: type: " + statusInfo.getType() + " - value: " + statusInfo.getResultCode());
    }
}

# Errors without Status

If the commerce listener is destroyed, the status will not be received. If the POS or the Payment Service crashes, an error status is returned indicating the connection is lost. In any of these scenarios, it is best to use the common recovery scenarios below, selecting the appropriate one for the state during which the error occurred.
```

{% endstep %}

{% step %}

### Common Error & Recovery Scenarios

#### Session Start Failure

This is generally caused by being in the wrong state when attempting to start a session (see [PSDK State Transitions](https://verifone.cloud/docs/tutorials/psdk_error_handling#psdk-state-transitions)). This can generally be resolved by querying the current state to determine what next steps ought to be taken, e.g., if the state is [TransactionManager.STATE\_SESSION\_OPEN](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionmanager), then the POS should end the old session. If this is still not working, it might be due to a mismatch of the android state and the POI state. Use [`TransactionManager.abort()`](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionmanager#abort) followed by [`TransactionManager.endSession()`](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionmanager#endsession), thoroughly resetting the state of the POI and allowing the current state to become accurate, after which starting the session should work smoothly.

It’s also possible for this to fail because the POI is not yet fully booted. In this case, it’s best to display a prompt to the cashier allowing them to retry the operation at their discretion, prompting them to make sure the POI is ready.

#### Recovering Event not received for Payment

This is generally caused either by a crash or a destroyed commerce listener. If a crash, when the application comes back up, it must log in, but starting a session will fail. Proceed to recovering the last transaction below.

If the listener is no longer valid, a new one must be created and added using [`PaymentSdk.addListener(listener)`](https://docs.verifone.com/psdk-api-latest/android-java/index/paymentsdkbase#addlistener-commercelistener2), then proceed to recovering the last transaction below.

If the connection is lost, the POS will receive a PaymentCompletedEvent with [`PaymentCompletedEvent.getStatus()`](https://docs.verifone.com/psdk-api-latest/android-java/index/paymentcompletedevent#getstatus) equaling [`StatusCode.DEVICE_CONNECTION_LOST`](https://docs.verifone.com/psdk-api-latest/android-java/index/statuscode). In this case, the only thing to do is to call [`PaymentSdk.tearDown()`](https://docs.verifone.com/psdk-api-latest/android-java/index/paymentsdkbase#teardown) and then initialize to recover the connection. To obtain the last transaction result, create a TransactionQuery object, use [`TransactionQuery.setQueryingLastTransaction(true)`](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionquery#setqueryinglasttransaction-boolean) to mark it as recovering the information about the most recent payment, and then examine the information returned in the [TransactionQueryEvent](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionqueryevent). The payment’s authorization result will be IN\_PROGRESS if it is still processing, it can be cancelled as [Cancel the Transaction](https://verifone.cloud/docs/tutorials/psdk_error_handling#cancel-the-transaction), or it will contain the actual result.

It is possible to abort a transaction if it is still in progress using [`TransactionManager.abort()`](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionmanager#abort). Sometimes this is preferred to recovering the status of the transaction, though it may require the customer to present their card again, or even possibly key in their loyalty information, and is not the ideal solution.

#### Recovering Event not received for Basket Action

This is generally caused either by a crash or a destroyed commerce listener. If this wasn’t received due to a crash, it is best to follow the steps for recovering a session. If the listener is no longer valid, a new one must be created and added using [`PaymentSdk.addListener(listener)`](https://docs.verifone.com/psdk-api-latest/android-java/index/paymentsdkbase#addlistener-commercelistener2). See [Create a Commerce Listener](https://verifone.cloud/docs/tutorials/psdk_error_handling#create-a-commerce-listener) for more information on commerce listeners.

#### Recovering a Session

Losing the connection to an active session on the POI is generally caused only by a crash. If a payment was not in progress, it’s best to start a new session and restore the basket. See [Session Start Failure](https://verifone.cloud/docs/tutorials/psdk_error_handling#session-start-failure), as simply calling [`TransactionManager.startSession(...)`](https://docs.verifone.com/psdk-api-latest/android-java/index/transactionmanager#startsession2-transaction) will likely fail, and then restore the basket ([Restoring a Basket from a Previous Order](https://verifone.cloud/docs/tutorials/psdk_error_handling#restoring-a-basket-from-a-previous-order)). If a payment was in progress when this occurred, see [Recovering Event not received for Payment](https://verifone.cloud/docs/tutorials/psdk_error_handling#recovering-event-not-received-for-payment).

#### Invalid Card and similar issues during Payment

There are many common error scenarios where a payment will not have an [AuthorizationResult ](https://docs.verifone.com/psdk-api-latest/android-java/index/authorizationresult)or even where the [PaymentCompletedEvent](https://docs.verifone.com/psdk-api-latest/android-java/index/paymentcompletedevent) will not have a Payment object. These cases include when the user has presented an invalid card (e.g. expired), or the card read has failed, or any number of other scenarios. The [`PaymentCompletedEvent.getStatus()`](https://docs.verifone.com/psdk-api-latest/android-java/index/paymentcompletedevent#getstatus) will be non-zero, and the string from [`PaymentCompletedEvent.getMessage()`](https://docs.verifone.com/psdk-api-latest/android-java/index/paymentcompletedevent#getmessage) will be localized for the cashier and should be displayed as a prompt, generally with an option to retry the payment.

## Printer Error Codes

| Error                     | Code |
| ------------------------- | ---- |
| STATUS\_SUCCESS           | 0    |
| STATUS\_ERROR             | 1    |
| STATUS\_OUT\_OF\_PAPER    | 2    |
| STATUS\_OVER\_TEMPERATURE | 4    |
| STATUS\_PAPER\_JAM        | 8    |
| STATUS\_LOW\_BATTERY      | 16   |
| {% endstep %}             |      |
| {% endstepper %}          |      |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.verifone.com/psdk-latest/reference-material/code-labs/error-handling.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
