Telegram API returns 400 error - entity parsing issue with Markdown format

I have a Telegram bot that sends error notifications to our chat. It worked perfectly in my Symfony 4.4 app but now I’m getting issues in Symfony 3.4.

When I try to send messages, I get this error:

400 Bad Request response:
{"ok":false,"error_code":400,"description":"Bad Request: can't parse entities: Can't find end of the entity starting at (truncated...)

The weird thing is that switching from Markdown to HTML parsing mode solves it completely. I can’t figure out why this happens.

Here’s my message format:

$notification = "$username encountered error at: $location\n`$errorMsg`\n$filename:$lineNumber";

And my sending functions:

public function callTelegramAPI($endpoint, $requestHeaders, $payload)
{
    $httpClient = new Client();
    $apiUrl = 'https://api.telegram.org/bot' . $this->botToken . '/' . $endpoint;

    return $httpClient->request('POST', $apiUrl, [
        'headers' => $requestHeaders,
        'form_params' => $payload,
    ]);
}

public function dispatchMessage($chatId, $messageText)
{
    try {
        return $this->callTelegramAPI('sendMessage', [
            'Content-Type' => 'application/x-www-form-urlencoded',
            'Accept' => 'application/json',
        ], [
            'chat_id' => $chatId,
            'parse_mode' => 'Markdown',
            'text' => $messageText,
            'disable_web_page_preview' => true,
        ]);
    } catch (Exception $e) {
        return $e->getMessage();
    }
}

Any ideas what could cause this difference between Symfony versions?

maybe it’s a special char in your msg, i had similar prob before. try to escape any backticks or underscores in $errorMsg, helped me with 400 errors before. markdown can be picky, ya know?

This looks like a character encoding issue that manifests differently between Symfony versions. I encountered exactly this when upgrading from an older Symfony installation. The root cause is typically related to how the HTTP client handles form parameter encoding.

In Symfony 3.4, try adding explicit UTF-8 encoding to your form_params by modifying your payload preparation. Before sending the message, ensure your text is properly encoded with mb_convert_encoding($messageText, ‘UTF-8’, ‘auto’). Also check if your error messages contain any special characters that might break markdown parsing - things like asterisks, underscores, or brackets that have special meaning in markdown.

Another approach is to sanitize the error message content specifically. I wrap any dynamic content that goes into backticks with a simple regex to escape problematic characters. The fact that HTML mode works suggests the issue is definitely with markdown parsing rather than the actual HTTP request structure.

I ran into something similar when migrating between Symfony versions. The issue is likely related to how different Symfony versions handle string escaping or character encoding. In my case, the problem was that certain characters in the error messages were being processed differently by the framework’s internal mechanisms.

Since HTML parsing mode works fine, I’d suggest sticking with that approach for now. You can achieve the same formatting by replacing your backticks with tags. Your message would become something like $username encountered error at: $location\n$errorMsg\n$filename:$lineNumber and change parse_mode to ‘HTML’. This gives you the same monospace formatting without the markdown parsing headaches. I’ve been using HTML mode exclusively for error notifications and it’s been much more reliable across different environments.