18 days ago
Description of the Issue:
I'm deploying a Telegram bot using Node.js and the Telegraf library on Railway. The bot works fine locally and also when deployed to Render, but fails on Railway when trying to set a webhook.
The failure seems to be caused by a semicolon (;) being appended automatically to the webhook URL constructed using process.env.APP_URL, even though the environment variable in Railway does not contain a semicolon in the value.
Error Message and Description:
When setting the webhook via:
CopyEdit
await bot.telegram.setWebhook(`${process.env.APP_URL}/webhook`);
I get this error:
CopyEdit
TelegramError: 404: Not Found payload: { url: 'https://bot-test-production-1293.up.railway.app/webhook'; }
Note the semicolon at the end of the webhook URL:
'https://bot-test-production-1293.up.railway.app/webhook';
This is not present in my variable value. It breaks the Telegram API call.
I also tested this via manual curl:
curl -X POST https://api.telegram.org/bot<my_token>/setWebhook \ -H "Content-Type: application/json" \ -d '{"url": "https://bot-test-production-1293.up.railway.app/webhook"} Telegram returned {"ok":true}, proving the endpoint is correct and reachable when the semicolon is not present.
Build/Deploy Logs:
There’s no error during build. Error occurs during runtime when the webhook is being set:
Failed to launch bot: TelegramError: 404: Not Found payload: { url: 'https://bot-test-production-1293.up.railway.app/webhook'; }
This shows the invalid semicolon.
Code Repository (If applicable):
[Private repo] – But I can provide a stripped-down minimal version if needed. The important code snippet:
const WEBHOOK_PATH = "/webhook"; const WEBHOOK_URL = $`{process.env.APP_URL}${WEBHOOK_PATH}`; await bot.telegram.setWebhook(WEBHOOK_URL);
Conclusion and Request:
I believe Railway is injecting a semicolon when interpolating or exporting APP_URL, even though it’s not in the variable editor. This causes third-party API integrations (like Telegram webhooks) to break silently.
Please help confirm:
Is this a known issue?
Can it be fixed or worked around?
Is there an internal sanitization step I need to disable?
This issue only happens on Railway and cost me a lot of debugging time. Happy to assist with more info or test cases.
7 Replies
18 days ago
This thread has been marked as public for community involvement, as it does not contain any sensitive or personal information. Any further activity in this thread will be visible to everyone.
Status changed to Open brody • 18 days ago
18 days ago
{ url: 'https://bot-test-production-1293.up.railway.app/webhook'; }
if you see, the ;
is outside the url
string value. The value probably doesn't have a ;
and it's only shown in the error message that is being printed. You can double check by doing console.log(WEBHOOK_URL)
and seeing what it is printing.
It looks the error is actually complaining about NOT_FOUND
which means the telegram endpoint you are hitting is unable to be found. Can you double check the token you are setting when initiating bot.telegram
?
pksunkara
{ url: 'https://bot-test-production-1293.up.railway.app/webhook'; }if you see, the ; is outside the url string value. The value probably doesn't have a ; and it's only shown in the error message that is being printed. You can double check by doing console.log(WEBHOOK_URL) and seeing what it is printing.It looks the error is actually complaining about NOT_FOUND which means the telegram endpoint you are hitting is unable to be found. Can you double check the token you are setting when initiating bot.telegram?
18 days ago
Thank you for your response.
Regarding console.log(WEBHOOK_URL)
: I’ve already tested this, and the returned URL does not include a semicolon.
As for bot.telegram token
: I'm confident the Telegram token is correct. I’ve cross-checked it multiple times, and it works perfectly in other environments — both when deployed locally and using the WSL terminal and when hosted on another site.
18 days ago
Then the only other possibility on why the code fails but the curl
command passes is that the server (or railway endpoint) might not be ready yet on Railway when the setWebhook
function is being run. Maybe add a few-second delay and see if it works?
pksunkara
Then the only other possibility on why the code fails but the curl command passes is that the server (or railway endpoint) might not be ready yet on Railway when the setWebhook function is being run. Maybe add a few-second delay and see if it works?
18 days ago
Thank you for your response.
I just added the following:
setTimeout(async () => { try { await bot.telegram.setWebhook(WEBHOOK_URL); console.log("
Webhook set to:", WEBHOOK_URL); } catch (err) { console.error("
Failed to set webhook:", err); } }, 5000); // Wait 5 seconds before setting the webhook
Despite placing setWebhook
after app.listen()
to ensure the server is fully loaded before it's called, I’m still encountering the same error.
valescaray
Thank you for your response.I just added the following:jssetTimeout(async () => { try { await bot.telegram.setWebhook(WEBHOOK_URL); console.log(" Webhook set to:", WEBHOOK_URL); } catch (err) { console.error(" Failed to set webhook:", err); } }, 5000); // Wait 5 seconds before setting the webhookDespite placing setWebhook after app.listen() to ensure the server is fully loaded before it's called, I’m still encountering the same error.
18 days ago
Try have the webhook callback be registered before you set it? https://telegraf.js.org/classes/Telegraf-1.html#webhookCallbac an app.use(bot.webhookCallback('/webhook'));
sim
Try have the webhook callback be registered before you set it? https://telegraf.js.org/classes/Telegraf-1.html#webhookCallbac an app.use(bot.webhookCallback('/webhook'));
17 days ago
Thank you for your response.
i actually did: app.use(bot.webhookCallback(WEBHOOK_PATH));
valescaray
Thank you for your response.i actually did: app.use(bot.webhookCallback(WEBHOOK_PATH));
17 days ago
Any advice on how i can get railway team to look into it. I have not gotten any feedback from them. I strongly believe its a fault from there end .