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.

CodeMeaningWhat to Do
0SuccessMark order paid, fulfill
1Insufficient balanceShow user-friendly message, suggest top-up
17Internal failureRetry once, then show generic error
26System busyBackoff and retry after 30 seconds
1001Unable to lock subscriber, transaction in progressUser has another M-Pesa transaction. Wait, retry.
1019Transaction expiredUser waited too long. Allow retry.
1025An error occurred while sending push requestNetwork or Safaricom-side issue. Retry.
1032Request cancelled by userUser pressed Cancel. Show retry button.
1037DS timeout user cannot be reachedUser didn't respond in 60s. Phone off or no signal.
2001Wrong PINUser 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 254
  • 254 712 345 678 — remove spaces
  • 254712345678 — 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: Some Pay Bills have a minimum (often KES 10). Set a UI minimum to match.
  • Above maximum: Default M-Pesa maximum is KES 250,000 per transaction. Above that you need special arrangements with Safaricom.

Callback Issues

"My callback never gets called"

Check in this order:

  1. Is your callback URL HTTPS? Daraja rejects HTTP. Use Let's Encrypt for free SSL.
  2. Is the URL publicly reachable? Test with curl -X POST https://yourdomain.com/api/mpesa/callback
  3. Is the URL whitelisted in Daraja portal settings?
  4. Does your server respond with HTTP 200 within 30 seconds?
  5. 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":

  • Test cases must succeed in sandbox — Safaricom reviews your sandbox transaction history
  • Production callback URL must be different from sandbox — both must be HTTPS
  • Real Pay Bill or Till must be active — confirm with your Safaricom relationship manager
  • Approval takes 1–3 business days — don't schedule launches expecting same-day

Production Performance Issues

STK prompts arrive slowly

Normal delivery is 5–10 seconds. If consistently slow (30+ seconds): 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), Safari 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 within 60 seconds. 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 within 30 seconds.

For the full STK Push implementation guide, see our M-Pesa STK Push Tutorial. For callback URL specifics, see M-Pesa Callback URLs Setup.