Some systems are built for specific people. For them, everything works smoothly; for others, the system is like a door without a handle—you know you should be able to enter, but no matter how you push, there is no response.
I encountered such a door while planning my trip to Uzbekistan.
The destination was Bukhara, departing from Tashkent. I found the official Uzbekistan Railways booking site eticket.railway.uz. I registered my account, selected my train (06:10 departure, 10:16 arrival), chose the carriage, and picked a window seat. But every time I pressed “Confirm,” the system canceled the order and kicked me back to the homepage.
No error message. Just a clean redirect, as if nothing had happened.
The travel agency quote is a mirror
I first asked a travel agency. Three tickets from Tashkent to Bukhara: 140 euros.
That number made me think. It wasn’t about whether it was expensive; it was about this: if I just accepted it, I would never know what the “true price” of the ticket was. Agencies have their value—some things do need a middleman—but this time, I wanted to know if I really couldn’t buy it myself first.
Being unable to use something is different from not having tried.
The system canceled the order itself
The page failing to load wasn’t a technical issue—at least not one of the “you can’t solve” variety. I opened the browser’s developer tools (DevTools → Network) and ran through the booking process again, watching every API request.
OrderID generated. The system received an orderId. Then, as I was redirected back to the homepage, I saw a POST request sent to:
/api/v1/universal-orders/cancel/{orderId}
It wasn’t me who canceled it. The system canceled it on its own.
Then I checked the order expiration API:
GET /api/v1/universal-orders/process/end-time/{orderId}
It returned:
{
"response": {
"endLifeTime": "2026-04-12T13:04:31.226000615"
}
}
It looked normal. But the time string was missing one thing.
A missing symbol
"2026-04-12T13:04:31.226000615"
This time string had no timezone information. No Z, no +05:00, nothing.
In JavaScript, the behavior of new Date("2026-04-12T13:04:31") depends on the browser’s local timezone. For a local in Uzbekistan (UTC+5), this time is interpreted as 13:04 local time, which is correct. For a user in Taiwan (UTC+8), the browser interprets it as 13:04 Taiwan time, which converts back to 05:04 UTC—exactly three hours earlier than Uzbekistan time.
The system gives you 15 minutes to complete the payment. But the moment your browser opens the page, it thinks the order has already been expired for three hours.
The timer hits zero immediately, cancels the order, and sends you back to the start.
This isn’t a complex bug, but it precisely locks out anyone from a different timezone—not because the system is intentionally unwelcoming, but because the system never imagined your existence.
Surgery in the browser
Once the problem was identified, the solution was simple.
I needed to intercept the API response at the moment it returned and add back the missing timezone info. Since Uzbekistan uses UTC+5 (Tashkent time), adding +05:00 at the end of the string allows the browser to parse it correctly.
The way to do it is to paste the following code into the DevTools Console before entering the booking page:
const _JSONparse = JSON.parse;
JSON.parse = function(text) {
const result = _JSONparse.call(this, text);
if (
result?.response?.endLifeTime &&
typeof result.response.endLifeTime === 'string'
) {
const str = result.response.endLifeTime;
if (
/^\d{4}-\d{2}-\d{2}T/.test(str) &&
!str.endsWith('Z') &&
!/[+\-]\d{2}:\d{2}$/.test(str)
) {
result.response.endLifeTime = str + '+05:00';
console.log('✓ endLifeTime fixed:', result.response.endLifeTime);
}
}
return result;
};
console.log('✓ Timezone fix enabled. You can proceed with booking.');
This code hijacks the browser’s JSON.parse. Every time an API response is parsed, it checks if endLifeTime is missing a timezone. If so, it appends +05:00. All other data remains untouched.
After execution, run through the process again: select train, select carriage, select seat, confirm. This time, the timer correctly counts down from 15 minutes, and the order stays on the confirmation page.

You click, but you don’t know where it leads
There is one important detail about the payment step.
After entering the payment page, you’ll see several payment options. One has a VISA icon, which theoretically should lead to a Stripe payment flow—the most direct choice for international travelers.
But in practice, the behavior is unstable. Sometimes it leads to Stripe; other times it redirects to a different system: OCTO Bank.

OCTO Bank is a local Uzbek bank. Its payment interface sometimes displays in Traditional Chinese, but based on the design, it seems geared toward Chinese payment channels. For a general international traveler, this path might not work.

If you are taken to OCTO Bank, I recommend canceling and trying again. Retrying a few times usually gets you into the proper Stripe flow. The reason for this is unclear—it might be random routing or related to browser state. As long as you aren’t on Stripe, do not enter any sensitive info; just try again.
Three tickets, 80 USD
In the end, three tickets from Tashkent to Bukhara cost roughly 80 USD.
The agency’s quote was 140 euros—about double the actual price.
I wasn’t calculating how much I saved. I cared about this: if I hadn’t looked into it, that margin would have simply vanished, and I would never have known it existed. It’s not that agency service has no value; it’s that this time, its value was “helping you bypass a problem that could have been solved,” and that problem was just a missing timezone string.
Sometimes, a system’s “incompatibility” isn’t malicious exclusion; it’s just careless forgetting.
Forgetful that there are people in the world with different timezones. Forgetful that UTC+8 isn’t the global default. Forgetful of what happens when a date string is missing its markers.
This kind of forgetting can be mended—and you don’t always have to wait for the official fix. Sometimes it just takes a dozen lines of code, a DevTools console, and a bit of patience that refuses to just give up.