Daraja API · Troubleshooting
M-Pesa Daraja API Common Errors and Fixes (2026)
Reference guide to every M-Pesa Daraja API error code you're likely to hit, with root causes and how to fix them.
If you're integrating M-Pesa Daraja API into a Kenyan website or app, you'll hit errors. The official documentation lists error codes but rarely explains why you're getting them. This guide covers the most common Daraja API errors with real root causes and fixes — based on what actually happens in production, not just the docs.
STK Push ResultCode Reference
When you receive an STK Push callback, the ResultCode field tells you what happened. Code 0 means success. Anything else is a failure of some kind.
| Code | Meaning | What to Do |
|---|---|---|
| 0 | Success | Confirm with an STK Query, then mark order paid and fulfill |
| 1 | Insufficient balance | Show user-friendly message, suggest top-up |
| 17 | Internal failure | Retry once, then show generic error |
| 26 | System busy | Backoff and retry after 30 seconds |
| 1001 | Unable to lock subscriber, transaction in progress | User has another M-Pesa transaction. Wait, retry. |
| 1019 | Transaction expired | User waited too long. Allow retry. |
| 1025 | An error occurred while sending push request | Network or Safaricom-side issue. Retry. |
| 1032 | Request cancelled by user | User pressed Cancel. Show retry button. |
| 1037 | DS timeout user cannot be reached | User didn't respond before the prompt timed out (roughly 1–3 minutes). Phone off or no signal. |
| 2001 | Wrong PIN | User entered wrong PIN. They can retry. |
Authentication Errors
"Invalid Access Token"
Token expired (1 hour TTL) or wasn't passed correctly in the Authorization header. Check: header format must be Bearer YOUR_TOKEN, not just the token. Cache tokens for ~50 minutes max.
"Invalid Authentication"
Consumer Key + Consumer Secret don't match a valid Daraja app, or you're using sandbox credentials against production endpoints (or vice versa). Check the environment URL.
"Invalid initiator information passed to processing API"
One of these:
- BusinessShortCode is wrong (typo, or sandbox shortcode used in production)
- PassKey was copied with leading/trailing whitespace
- Timestamp format wrong — must be YYYYMMDDHHMMSS without separators
- Password (base64 of ShortCode + PassKey + Timestamp) computed incorrectly
Phone Number Format Errors
Daraja expects phone numbers in international format with country code: 2547XXXXXXXX (12 digits total). Common mistakes:
+254712345678— remove the +0712345678— replace leading 0 with 254254 712 345 678— remove spaces254712345678— correct
Use a regex like ^254[17]\d{8}$ to validate before submitting.
Amount Format Errors
- Decimals: Daraja only accepts integers. KES 100.50 fails — round to 100 or 101.
- Zero or negative: Rejected. Validate amount > 0 server-side.
- Below minimum: The M-Pesa minimum is KES 1. Set a UI minimum to match.
- Above maximum: The M-Pesa maximum is KES 250,000 per transaction, and a customer can send at most KES 500,000 a day. Split larger amounts or use another method.
Callback Issues
"My callback never gets called"
Check in this order:
- Is your callback URL HTTPS? Daraja rejects HTTP. Use Let's Encrypt for free SSL.
- Is the URL publicly reachable? Test with
curl -X POST https://yourdomain.com/api/mpesa/callback - Is the URL whitelisted in Daraja portal settings?
- Does your server respond with HTTP 200 quickly?
- Did you get the response from the STK Push initiation? If
ResponseCode≠ 0 there, the request never reached the customer.
"Callback called multiple times"
Safaricom retries callbacks if your server doesn't respond 200, or sometimes even if it does (rare). Make your callback handler idempotent — check if the order is already marked paid before processing again. Use the MpesaReceiptNumber as the deduplication key.
"Go Live" Approval Issues
When applying for production access via "Go Live":
- You need an M-Pesa Org Portal administrator — the Go Live form asks for the username of a Business Administrator or Business Manager on the Org Portal (case-sensitive), and sends an OTP to that person's Safaricom line
- The production passkey comes by email — Safaricom emails it to the developer after go-live; it is not the sandbox passkey
- Real Pay Bill or Till must be active — confirm with your Safaricom relationship manager
- Approval comes within 24 working hours (Monday to Friday, 8am to 5pm) — but setting up the Org Portal administrator first can take longer, so don't schedule launches expecting same-day
Production Performance Issues
STK prompts arrive slowly
Prompts normally arrive within seconds. If they are consistently slow: check for Safaricom-side incidents at @safaricomltd. Also verify your server isn't adding latency before calling Daraja.
Some users never receive prompts
Likely causes: phone is off, low signal area, M-Pesa subscription issue (rare), Safaricom outage in their area. Always provide a Pay Bill fallback with clear instructions for users who can't complete STK.
Frequently Asked Questions
What does ResultCode 1032 mean in M-Pesa?+
ResultCode 1032 means "Request cancelled by user" — the customer received the STK Push prompt but pressed Cancel instead of entering their PIN. This is normal user behavior, not an error in your code. Show a friendly retry option.
What does ResultCode 1037 mean in M-Pesa?+
ResultCode 1037 means "DS timeout user cannot be reached" — the STK Push prompt was sent but the user didn't respond before it timed out (roughly 1–3 minutes, depending on the phone). Could be: phone off, no network, or user simply didn't see the prompt. Allow them to retry.
Why am I getting "invalid initiator information" on Daraja?+
This usually means the BusinessShortCode + PassKey + Timestamp combination doesn't match what Safaricom expects. Most common cause: timestamp format wrong (must be YYYYMMDDHHMMSS, no separators) or PassKey copied with extra whitespace.
How do I handle Daraja API access token expiry?+
Access tokens expire after 1 hour. Cache the token in memory or Redis with a TTL of ~50 minutes (5-minute safety margin), then refresh. Avoid generating a new token for every request — Safaricom rate-limits token generation.
Why is my M-Pesa callback never received?+
Check: (1) callback URL is HTTPS (HTTP is rejected), (2) URL is publicly accessible (no localhost or behind firewalls), (3) URL is whitelisted in Daraja portal settings, (4) your server responds with HTTP 200 quickly.
For the full STK Push implementation guide, see our M-Pesa STK Push Tutorial. For callback URL specifics, see M-Pesa Callback URLs Setup.