Bonaventure OgetoBy Bonaventure Ogeto|

Common Mobile Money API Errors in Tanzania and How to Handle Them

The most common mobile money API errors in Tanzania are: timeouts (customer does not respond to the payment prompt within the allowed window), insufficient funds (customer does not have enough in their wallet), invalid phone numbers (wrong format or non-existent number), callback delivery failures (your server was unreachable when the callback arrived), expired authentication tokens or session keys, and duplicate callback processing. Each error needs specific handling in your code. The good news: these errors are the same across M-Pesa, Tigo Pesa, and Airtel Money. The error codes differ, but the categories and handling strategies are identical.

Timeout Errors: The Most Common Problem

Timeouts are the error you will deal with most often. The scenario: you send a payment request, the customer gets a prompt on their phone, and they do not respond. Maybe they are away from their phone. Maybe their phone is off. Maybe they changed their mind. The prompt expires after 60 to 90 seconds, and you get a timeout callback (or no callback at all).

How to handle timeouts:

  • Set a clear timeout window in your system. After 90 seconds (or whatever the provider's timeout is), mark the transaction as "timed_out" in your database.
  • Show the customer a clear message. "Payment request has expired. Please try again." Include a retry button that allows them to re-initiate the payment without creating a new order.
  • Implement a status check. Some providers offer a transaction status query API. Use this as a fallback: if you do not receive a callback within your expected window, query the provider (or aggregator) for the transaction status. This catches cases where the callback was delayed or lost.
  • Handle late callbacks. Sometimes the customer confirms just before the timeout, and the callback arrives a few seconds after your system has already marked it as timed out. Your callback handler should check if the transaction was marked as timed out and, if the callback indicates success, update it to successful. Do not ignore a success callback just because your timer expired.

Timeouts are not really errors in the traditional sense. They are a normal part of the mobile money flow. Design for them as an expected state, not an exception.

Insufficient Funds and Customer-Side Failures

The second most common error category: the customer tries to pay but something fails on their end.

Insufficient funds: The customer does not have enough money in their mobile money wallet to cover the payment amount. You receive a callback indicating the failure reason.

How to handle it:

  • Display a clear, non-technical message: "Payment could not be completed. Your mobile money balance may be insufficient for this transaction."
  • Do not display the raw error code. "Error: INS_FUNDS" means nothing to a customer.
  • Offer a retry option. The customer may need to top up their wallet and try again.
  • Consider showing the total amount prominently so the customer can check if they have enough before initiating payment.

Wrong PIN: The customer enters the wrong PIN. Most providers allow a few attempts before locking the wallet. You receive a failure callback.

Customer declined: The customer sees the prompt and actively cancels it. You receive a callback indicating the customer declined.

Account restrictions: The customer's mobile money account may be suspended, locked, or under a transaction limit. These are less common but produce specific error codes.

All of these are customer-side issues. Your code cannot fix them. What your code can do is provide clear, helpful messages so the customer understands what happened and what to do next. Map every provider error code to a human-readable message.

Authentication and Connection Errors

These errors happen between your server and the mobile money API, before the customer is even involved.

Expired session key or access token:

  • Vodacom M-Pesa uses session keys that expire. Safaricom Daraja and Airtel Money use OAuth tokens that expire. If you try to make an API call with an expired token, you get an authentication error.
  • The fix: implement token caching with automatic renewal. Before making an API call, check if your token is still valid. If not, request a new one. Do not request a new token for every call (that wastes time and API quota). Cache the token and renew it before it expires.

Invalid credentials:

  • Happens when your API keys, consumer keys, or session keys are wrong. Most commonly caused by mixing up sandbox and production credentials, or by copying credentials with extra whitespace.
  • Triple-check that your environment variables match the correct environment (sandbox or production). Trim whitespace from credential strings.

Network errors and timeouts on the API call itself:

  • Your server cannot reach the provider's API. Could be a network issue on your end, on the provider's end, or anywhere in between.
  • Implement retry logic with exponential backoff. Try the request again after 1 second, then 2 seconds, then 4 seconds. After 3 to 5 retries, give up and show the customer an error.
  • Log the error details. If it happens consistently, the issue may be with your hosting provider's network connectivity to the telco's servers.

SSL/TLS errors:

  • Mobile money APIs require HTTPS. If your server's SSL certificate is expired or misconfigured, API calls may fail. Keep your certificates current.

Callback Failures: When You Never Get the Result

This is the error category that causes the most confusion: you sent a payment request, the customer may or may not have confirmed, and you never receive a callback. Your system is stuck in "pending" state.

Why callbacks fail to arrive:

  • Your callback URL was unreachable when the provider tried to deliver it (server was down, network issue, firewall blocked the request).
  • Your callback endpoint returned an error (500 status code, unhandled exception). Some providers do not retry after receiving an error response.
  • Your callback URL was wrong (typo, wrong domain, HTTP instead of HTTPS).
  • The provider's callback delivery system experienced a delay or failure.

How to handle missing callbacks:

  1. Never assume no callback means failure. The payment may have succeeded and the callback was lost. If you mark the transaction as failed and the customer was actually charged, you have a reconciliation problem.
  2. Implement a status check fallback. Most providers and aggregators offer a transaction status query endpoint. If you do not receive a callback within your expected window (90 to 120 seconds), query the status API. This is your safety net.
  3. Build a reconciliation workflow. At the end of each day, compare your transaction records with the provider's settlement report. Identify any mismatches. This catches cases where a callback was lost and the status check also missed it.
  4. Monitor your callback endpoint. Log every incoming callback with timestamps. If you notice gaps, investigate your server's availability during those periods. Set up uptime monitoring for your callback endpoint specifically.

A well-built payment integration treats the callback as the primary mechanism and the status check as the fallback. Both should lead to the same result for any given transaction. If they disagree, the status check (which queries the provider directly) is the source of truth.

Duplicate Callbacks and Idempotency

Sometimes you receive the same callback twice. Maybe the provider's retry logic kicked in. Maybe a network glitch caused a duplicate delivery. If your code processes the same success callback twice, you might credit the customer's order twice, send two confirmation emails, or create duplicate records.

The solution: idempotent callback handling.

Every callback includes a unique transaction reference (different names per provider, but the concept is the same). When your callback handler runs:

  1. Extract the transaction reference from the callback payload.
  2. Check if you have already processed a callback with this reference.
  3. If yes, return a success response to the provider but do nothing else. The transaction was already handled.
  4. If no, process the callback normally and record that this reference has been processed.

This logic is simple but critical. Without it, your system is vulnerable to duplicate processing, and mobile money providers can and do send duplicate callbacks.

Store the raw callback payload alongside the transaction reference. If you ever need to re-process a callback (because your handler had a bug), the raw data lets you replay it correctly.

This idempotency pattern is identical across all three Tanzanian providers and across every mobile money API globally. Learn it once, use it everywhere.

Building an Error Handling Strategy

Rather than handling each error ad hoc, build a structured error handling strategy:

1. Categorize errors.

  • Customer-side errors (insufficient funds, wrong PIN, declined): Show a clear message. Offer a retry.
  • Authentication errors (expired token, invalid credentials): Retry with a fresh token. If that fails, alert your operations team.
  • Network errors (timeout on API call, connection refused): Retry with backoff. After max retries, show a temporary failure message.
  • Callback errors (missing, duplicate, malformed): Use status check as fallback. Log for investigation.

2. Map error codes to messages. Create a mapping from provider-specific error codes to customer-friendly messages. Do this once per provider and keep it updated as the provider adds new error codes.

3. Log and monitor. Log every error with the full context: timestamp, transaction reference, error code, error message, request payload, response payload. Set up alerts for error rate spikes. If your timeout rate suddenly jumps from 5% to 30%, something has changed at the provider level and you need to investigate.

4. Learn the pattern once. McTaba's M-Pesa Integration for Developers course (KES 9,999 / ~TZS 200,000) covers error handling as a core topic. The patterns are the same for Vodacom, Tigo Pesa, Airtel Money, and any aggregator. The error codes differ, but the handling architecture does not.

Key Takeaways

  • The same categories of errors occur across all three Tanzanian mobile money providers: timeouts, insufficient funds, invalid numbers, expired auth, and callback failures. Learning to handle them on one provider prepares you for all three.
  • Timeouts are the most common error and the hardest to handle. The customer simply does not respond to the payment prompt. Your system needs a clear timeout state, a way to check the transaction status, and a retry mechanism.
  • Never trust a missing callback to mean failure. Callbacks can be delayed due to network issues. Always implement a status check (polling) as a fallback.
  • McTaba teaches error handling patterns in the M-Pesa Integration course (KES 9,999 / ~TZS 200,000). The patterns apply directly to all three Tanzanian providers and any aggregator.

Frequently Asked Questions

Are the error codes the same across M-Pesa, Tigo Pesa, and Airtel Money?
No. Each provider (and each aggregator) uses its own error codes and messages. However, the categories of errors are identical: timeouts, insufficient funds, wrong PIN, declined, authentication failure, network error. Build your error handling around categories, not specific codes. Map provider-specific codes to your internal categories.
What if a customer was charged but my callback failed?
This is the most important edge case to handle. Use the transaction status check API to verify whether the payment actually went through. If it did, update your records and fulfill the order. If you cannot determine the status programmatically, flag it for manual reconciliation. Never assume the payment failed just because you did not receive a callback.
How do I test error handling in the sandbox?
Most sandbox environments let you simulate specific error scenarios: successful payments, insufficient funds, timeouts, and declined transactions. Use specific test phone numbers or test amounts to trigger different outcomes. Check your aggregator's documentation for the exact test scenarios they support. Test every error category before going live.

Ready to build real-world apps?

Join the McTaba Labs full-stack marathon (4 months full-time · 6 months part-time). Learn M-Pesa, USSD, and WhatsApp engineering while shipping 8 production apps.

Apply to the McTaba Marathon