Bug Description
When Magento is configured with store codes in URLs (e.g. /sa-ar/, /sa-en/), the Tamara payment callback URLs (success, failure, cancel) intermittently return HTTP 500 errors. Customers who complete payment on Tamara's checkout page are redirected back to the store and see an error page instead of their order confirmation.
Root Cause
Controller/Router.php assumes the URL path always starts with tamara/payment/{order_id}/{action}, using hardcoded indices ($urlParts[0], $urlParts[1], etc.).
However, Magento does not always strip the store code prefix from $request->getPathInfo() before custom routers are invoked. When the store code is present, the path becomes {store_code}/tamara/payment/{order_id}/{action}, shifting all indices by 1. The router fails to match, returns null, and Magento's FrontController retries all routers until it hits the 100-iteration limit, resulting in:
Front controller reached 100 router match iterations
Affected URLs
/sa-ar/tamara/payment/189720/success?orderId=...&paymentStatus=approved → 500
/sa-en/tamara/payment/191364/success?paymentStatus=approved&orderId=... → 500
/sa-ar/tamara/payment/189542/failure?paymentStatus=expired&orderId=... → 500
Environment
Magento 2.4.x with multi-store setup (store codes in URLs enabled)
Tamara_Checkout module v1.1.7 (also confirmed unchanged in v1.12.47 on GitHub)
Stores: sa-ar, sa-en, ae-en, ae-ar, etc.
Impact
Customers who successfully pay via Tamara see a 500 error page instead of order confirmation
Order authorization may not complete (the Success controller handles authorizeOrder())
In our case, 11 unique orders were affected over a 3-week period (Feb 3 – Feb 24, 2026)
Proposed Fix
The match() method should try matching with and without a store code prefix. Here is the fix we applied via a custom module override:
public function match(RequestInterface $request)
{
$identifier = trim($request->getPathInfo(), '/');
$urlParts = explode('/', $identifier);
$offset = $this->resolveOffset($urlParts);
if ($offset === -1) {
return;
}
$request->setModuleName(self::MODULE_NAME)
->setControllerName(self::CONTROLLER_NAME)
->setActionName($urlParts[$offset + 3])
->setParam('order_id', $urlParts[$offset + 2]);
$request->setAlias(\Magento\Framework\Url::REWRITE_REQUEST_PATH_ALIAS, $identifier);
return $this->actionFactory->create(\Magento\Framework\App\Action\Forward::class);
}
private function resolveOffset(array $urlParts): int
{
// Standard: /tamara/payment/{id}/{action}
if ($this->matchesPattern($urlParts, 0)) {
return 0;
}
// With store code prefix: /{store}/tamara/payment/{id}/{action}
if (isset($urlParts[4]) && $this->matchesPattern($urlParts, 1)) {
return 1;
}
return -1;
}
private function matchesPattern(array $urlParts, int $offset): bool
{
if (empty($urlParts[$offset]) || empty($urlParts[$offset + 1])
|| empty($urlParts[$offset + 2]) || empty($urlParts[$offset + 3])) {
return false;
}
return $urlParts[$offset] === self::MODULE_NAME
&& $urlParts[$offset + 1] === self::CONTROLLER_NAME
&& is_numeric($urlParts[$offset + 2])
&& in_array($urlParts[$offset + 3], $this->actions, true);
}
Bug Description
When Magento is configured with store codes in URLs (e.g. /sa-ar/, /sa-en/), the Tamara payment callback URLs (success, failure, cancel) intermittently return HTTP 500 errors. Customers who complete payment on Tamara's checkout page are redirected back to the store and see an error page instead of their order confirmation.
Root Cause
Controller/Router.php assumes the URL path always starts with tamara/payment/{order_id}/{action}, using hardcoded indices ($urlParts[0], $urlParts[1], etc.).
However, Magento does not always strip the store code prefix from $request->getPathInfo() before custom routers are invoked. When the store code is present, the path becomes {store_code}/tamara/payment/{order_id}/{action}, shifting all indices by 1. The router fails to match, returns null, and Magento's FrontController retries all routers until it hits the 100-iteration limit, resulting in:
Front controller reached 100 router match iterations
Affected URLs
/sa-ar/tamara/payment/189720/success?orderId=...&paymentStatus=approved → 500
/sa-en/tamara/payment/191364/success?paymentStatus=approved&orderId=... → 500
/sa-ar/tamara/payment/189542/failure?paymentStatus=expired&orderId=... → 500
Environment
Magento 2.4.x with multi-store setup (store codes in URLs enabled)
Tamara_Checkout module v1.1.7 (also confirmed unchanged in v1.12.47 on GitHub)
Stores: sa-ar, sa-en, ae-en, ae-ar, etc.
Impact
Customers who successfully pay via Tamara see a 500 error page instead of order confirmation
Order authorization may not complete (the Success controller handles authorizeOrder())
In our case, 11 unique orders were affected over a 3-week period (Feb 3 – Feb 24, 2026)
Proposed Fix
The match() method should try matching with and without a store code prefix. Here is the fix we applied via a custom module override: