Home · Blog · PEER_ID_INVALID and “bot cannot write first”: reasons and workaround

PEER_ID_INVALID and “bot cannot write first”: reasons and workaround

· updated · Command CHBT · Telegram, Errors

The PEER_ID_INVALID error appears in two situations: the bot sends a message using an incorrect identifier or tries to write to a person who has never opened it. The second case is not a glitch, but a Telegram rule: the bot cannot start a conversation first. It leads to things that break the plans of many: you cannot download a list of phone numbers and send them out, you cannot write to channel subscribers who have not logged into the bot, you cannot “catch up” with a client from CRM with a message. Below is what each Bot API error means, how PEER_ID_INVALID differs from blocking, how to build a database that can be used to write, and how this is reflected in the CHBT mailing statistics.

Short answer

PEER_ID_INVALID — Telegram’s response to an attempt to send a message “to nowhere.” Telegram does not find the interlocutor to whom the bot has access: either the chat ID is incorrect, or this person has never written to the bot or clicked “Start”. For a bot, such a user does not exist - even if you have his phone number, username and he is subscribed to your channel.

This is not fixed on the bot’s side or in the constructor. The only way to get the right to write to a person is for him to open a conversation with the bot: click “Start”, send /start or any message, follow the deep link. From this moment on, the bot can write to him without time limits - until the person blocks the bot.

If you see this error in the mailing statistics or in the integration logs, we will further analyze what exactly is the reason for you and what to do about it. If the error occurs during normal correspondence with a bot that previously answered, that’s a different story, see below. checklist “Telegram bot is silent”.

Dictionary of Telegram Bot API errors about delivery

Telegram responds with different texts to similar situations. They are confused, and they are treated differently.

Reply TelegramWhat happenedWhat do
400 Bad Request: PEER_ID_INVALIDID is not recognized as a chat accessible to the bot: incorrect ID, username instead of ID, person has never written to the botcheck ID; get /start from person
403 Forbidden: bot can't initiate conversation with a userThe ID is correct, but the person did not open the botonly /start from the human side
400 Bad Request: chat not foundthere is no chat with this ID or the bot has never seen itcheck ID, for channels - prefix -100
403 Forbidden: bot was blocked by the userthe person wrote to the bot, and then clicked “Block”remove from broadcasts; You can't write until it unlocks
403 Forbidden: user is deactivatedaccount deletedremove a contact from the database
403 Forbidden: bot can't send messages to botstrying to write to another botbots don’t write to each other - no way
400 Bad Request: group chat was upgraded to a supergroup chatthe group became a supergroup and changed IDtake a new ID from the field migrate_to_chat_id
429 Too Many Requests: retry after Nsending limit exceededwait N seconds, slow down

The first two lines are about the same rule “person writes first,” Telegram just formulates it differently depending on how the identifier is transmitted. The third is most often a typo or incorrect format. The fourth and fifth are the state of the base, which changes over time. The last two are technical and do not apply to the rule.

The “man writes first” rule and why it doesn’t work

A Telegram bot can only send a message to someone who has written to it at least once. This is protection against spam at the platform level: otherwise, any bot could send messages using identifiers, and the messenger would turn into mail in 2005.

The rule does not depend on the instrument. Not a single constructor, nor its own code on the Bot API, nor paid services bypass it - if someone promises “distribution using a database of numbers in Telegram,” we are either talking about personal accounts and gray schemes with a ban, or about SMS. The CHBT bot obeys the rule just like any other.

What counts as “wrote first”:

  • clicked the “Start” button in a chat with a bot - this sends the /start command;
  • followed the deep link https://t.me/имя_бота?start=payload and clicked “Start”;
  • sent any message to the bot by text.

What does not count: subscription to your channel, where the bot is the administrator; membership in the group where the bot sits (in the group the bot can respond, but not in a personal message to this person); phone number in your CRM; correspondence with your personal account. The same principle applies in MAX: the bot receives an event bot_startedwhen a person opens it, and only after that can send service messages - more about this in the article about notifications to clients via MAX bot.

PEER_ID_INVALID, blocking and “chat not found”: how they differ for your database

Three errors are three different contact states, and from the base point of view they are not equal.

Never wrote (PEER_ID_INVALID, can't initiate conversation). This person is not in the bot's database. It may be in your CRM, in the list of channel subscribers, in a table from an exhibition - but for a bot it is an empty place. He cannot be “added to the database” manually: only he himself can do this. The strategy is to give him a reason to open the bot, see next section.

Blocked (bot was blocked by the user). The person was in the database, received messages and clicked “Block bot” - most often after a mailing that he considered unnecessary. The contact in CHBT remains with all the history and tags, but delivery is not possible until he unblocks it himself. The strategy is to exclude them from mailing lists and not try to reach them: every attempt is an error in statistics and an extra load on the queue.

Invalid ID (chat not found). There is a technical glitch on your end if you are submitting via custom code or integration. The person may be in the database, but you are knocking on the wrong door. The strategy is to look for the error in the data, not in the client.

A practical consequence for the owner of the bot on the constructor: since CHBT sends messages only to contacts who themselves wrote to the bot, PEER_ID_INVALID and chat not found almost never appear in mailing lists. Delivery errors there are blocked and deleted accounts, that is, the natural aging of the database.

Where does the wrong ID come from if you write your own code?

This section is for those who send messages via the Bot API themselves or have connected the bot to an external system via a webhook. Typical sources PEER_ID_INVALID and chat not found:

  • Username instead of chat_id. Send a message to the user by @username not possible - only by numeric ID. Only public channels and groups work by username, and only if the bot is a member of them.
  • Phone instead of ID. Bot API does not know phone numbers. The number received through the “Share Contact” button is data, not a delivery address.
  • ID from another library. MTProto client libraries (Telethon, Pyrogram) work with the “ID + access hash” pair and produce PeerIdInvalid, if this user’s session has not yet been “seen”. In the Bot API, an access hash is not needed, but a user ID taken from someone else's session does not give anything if the person did not write to your bot.
  • Channel ID without prefix. Channel and supergroup IDs in the Bot API begin with -100. View ID 1234567890 from the link t.me/c/1234567890/… needs to be turned into -1001234567890.
  • The group became a supergroup. After the upgrade, the ID changes. Telegram sends migrate_to_chat_id - keep the new one and don’t use the old one anymore.
  • Cropped ID. User IDs have long since exceeded 2³¹. An int32 field in a database or table that “rounds” long numbers corrupts the ID when saved. Store as int64 or string.

There is only one rule: the only reliable one chat_id — the one that came in the update from the user himself (message.chat.id). Anything obtained in a different way is a reason for error.

How to build a database that can be used to write

Since the bot does not write first, the owner’s task is to make sure that the client writes first, and at the right time and with the right context. Tool - deep link: link to a bot with payload, which triggers a trigger in CHBT “Deep link” and the script starts from the right place.

  • Site. The “Write to Telegram” button leads to a deep link, and not to the manager’s personal account. The CHBT widget on the website is the second input: the contact from the widget goes into the same database.
  • Channel. Link to the bot in the description, in the pin and in every post where there is material or an offer. Channel subscriber ≠ bot contact until he switches over.
  • Offline. Section "QR campaigns" in CHBT generates a QR code with a deep link - for an insert in a parcel, a stand, a business card, a receipt. The Buyer Bot template is built on exactly this: the buyer scans, opens the bot, and becomes a contact with the campaign tag.
  • Moment of order. If you want to send order statuses or appointment reminders, ask the client to open the bot at the time of checkout: “click to receive status in Telegram.” The “Notifications” template collects contacts specifically for this task.
  • Existing phone database. You cannot turn it into message recipients in any constructor - import will create cards, but not conversations. The working path is an SMS or letter with a deep link and a clear reason to go: discount, checklist, order status. The conversion rate of such transitions is low, so it’s better to start collecting the database in the bot today than to catch up with it later.

Separately, consent. Template “Consent to mailing list” not just collects a contact, but receives an explicit “yes, send” from the person and puts a tag, which is then used to select the audience. This is both a requirement of Federal Law 152 and protection against blocking: those who agree are less likely to click “Block”.

What does the mailing statistics show in CHBT

Section “Mailmails” (Basic plan and higher) sends messages through the queue one at a time, with a pause of 50 ms - no faster than 20 per second, this is below the Telegram limit for bulk sending (about 30 messages per second). The audience is selected by tags from contacts who have already written to the bot, so the newsletter doesn’t even try to “write first.”

After sending, the mailing card contains two numbers: sent and errors. Mistakes are almost always bot was blocked by the user and user is deactivated: people who have left the base since their last contact with you. How to read this number:

  • A small and stable proportion of errors from mailing to mailing is the norm, natural aging of the database.
  • A jump compared to previous broadcasts - the database lay without contact for several months, or the previous mailing was unnecessary.
  • There are a lot of errors, and with each mailing there are more of them - either the database was collected in a “cold” way (people opened the bot for a one-time file and did not wait for messages), or the frequency of broadcasts is too high.

What to do with errors: do not repeat sending to the same contacts - the blocking will not be removed by repeating it. Contacts remain in the “Contacts” section with history; It makes sense to maintain a separate tag for those who have blocked and exclude them from the audience of future broadcasts. Read about how to return a “sleeping” database without getting a wave of blocking. about database reactivation via bot.

If the message needs to be sent from an external system

A common flow: the order has changed its status in your accounting system - you need to notify the client in Telegram. Through custom code this will lead to PEER_ID_INVALID from everyone who did not write to the bot. But for those who wrote, in CHBT you need to understand what exactly each tool can do.

Trigger "Incoming webhook" - this is starting a script from the outside: your system sends a POST with a secret to the address CHBT, and the script starts as a separate event. It is suitable for official tasks - “payment completed” → action “Transaction in CRM” and “Notify operator”. What he doesn’t do: he doesn’t find a specific client on Telegram and write to him in his conversation. The script for the incoming webhook is launched as a new conversation in the widget channel, and not as a message to Ivanov, who opened the bot yesterday. The scheme “the system learned about the shipment → the client received a message in Telegram” does not work through this trigger, and it is not worth promising it to clients.

Addressed notifications in CHBT are delivered in three ways, and in all three the “human writes first” rule is observed by itself:

  • the client asks himself — “Keyword” trigger or “Where is my order” button, then “Data collection” with the order number and action “HTTP request” (your server’s response is inserted into the message through the “into variable” field); the order status from Ozon and Wildberries by number CHBT is not received, such questions go to the operator;
  • mailing by tag - for events that concern a group rather than one person;
  • operator from "Conversations" — for isolated cases: there is already a conversation, which means the message will get through.

The reverse direction, the "HTTP request" from the script, sends the contact data and variables to your system. The format of incoming and outgoing requests is described in the help by webhook, and a detailed analysis of the same circuit for MAX is in the article about notifications to clients via bot.

About import. In “Contacts” there is “CSV Import”, but it does not give the right to write: an imported contact that does not have a conversation with a bot in Telegram or MAX is unreachable for the platform - sending messages to it will result in errors. Import is useful to pull up names, phone numbers and tags for people who have already opened the bot, and not to “load the database”.

Diagnostic checklist

  1. Where did the error occur? In the mailing statistics, CHBT is blocking, see the section on statistics. In your code logs, follow the error table above.
  2. Did the person write to the bot? Check in the “Contacts” section: if there is no card, he did not open the bot, and no ID will help.
  3. Is the ID correct? A number, not a username or phone number; for channels - with -100; stored without loss of digits.
  4. Didn't you block it? Answer bot was blocked unambiguous Unsubscribe from mailing lists and wait.
  5. Isn't that the limit? 429 — sending rate. In CHBT the queue throttles itself; in your code respect retry_after.

Main conclusion: PEER_ID_INVALID - this is not a breakdown, but a reminder that the bot base is built only by the hands of clients. Place a link to the bot wherever you are found, collect consent, monitor the error rate - and the rule will no longer be a problem. A bot with deep links, QR campaigns and consent to mailing lists is assembled in CHBT on the Free plan; broadcasts - on Basic for 650 ₽ per month. Connecting a channel - on the page Telegram bot designer. Create a bot and start collecting a database →

More on the blog