Link Search Menu Expand Document

FAQ

Here’s a list of common MadelineProto questions and answers.

How do I solve “Fiber stack allocate failed” and “Fiber stack protect failed” errors?

The PHP engine mmap’s two memory regions for each forked green thread: one for the stack, and one for the final guard page.

MadelineProto can use hundreds or even thousands of concurrent, low-overhead green threads to handle updates with the maximum performance.

This error is emitted when the maximum number of configured mmap’ed regions is reached: you must increase the vm.max_map_count kernel config to 262144 to fix.

To fix, run the following command as root:

echo 262144 | sudo tee /proc/sys/vm/max_map_count

To persist the change across reboots:

echo vm.max_map_count=262144 | sudo tee /etc/sysctl.d/40-madelineproto.conf

On Windows and WSL, increasing the size of the pagefile might help; please switch to native Linux if the issue persists.

How do I get the chat ID and/or sender ID of a message in the event handler?

Use this code:

// Chat ID
$id = $this->getId($update);

// Sender ID, not always present
from_id = isset($update['message']['from_id'])
    ? $this->getId($update['message']['from_id'])
    : null;

How do I extract the ID of a message sent using sendMessage/sendMedia/etc…?

Use this code:

$id = $MadelineProto->extractMessageId(
    $MadelineProto->messages->sendMessage(peer: 'danogentili', message: 'test')
);

How do I execute a function periodically (like cron)?

Use this code:

use danog\MadelineProto\EventHandler;
use danog\MadelineProto\Settings;
use danog\Loop\GenericLoop;

class MyEventHandler extends EventHandler
{
    private PeriodicLoop $cron1;

    public function onStart(): void
    {
        // Execute every 1.0 seconds
        $this->cron1 = new PeriodicLoop($this->cron1(...), "Cron 1", 1.0);
        $this->cron1->start();
    }

    /**
     * Cron function 1.
     * Executed every second.
     */
    private function cron1(): bool
    {
        $this->echo("Current time: ".time().PHP_EOL);

        // The loop can be stopped from the outside by calling $this->cron1->stop();

        // You can also return true here to stop the loop from the inside.
        return false;
    }
}

$settings = new Settings;

MyEventHandler::startAndLoop('bot.madeline', $settings);

See the danog/loop documentation for more info.

Do I need cron to run MadelineProto?

Generally, you don’t.

To keep your MadelineProto bot online forever:

  • If running via CLI, use docker » or a screen while :; php bot.php;done session.
  • If running via web: MadelineProto will self-restart automatically: however, please note that this self-restart logic may fail in case of a physical server reboot or web server/php-fpm restart, so it’s always a better idea to run via CLI, or use a cron to periodically ping the bot’s URL.

How do I use a database in MadelineProto?

First of all, never use PDO.

If you only want to reduce RAM usage of your bot, use this code:

$settings = (new \danog\MadelineProto\Settings\Database\Mysql)
    ->setUri('tcp://localhost')
    ->setPassword('pass');

MyEventHandler::startAndLoop('bot.madeline', $settings);

You can also use Postgresql or Redis, see the database docs for more info ».

If you also want to store data of your bot in a database, use this code:


use danog\MadelineProto\EventHandler;

class MyEventHandler extends EventHandler
{
    private int $messageCounter = 0;

    /** Which properties to save in the database */
    public function __sleep(): array
    {
        return ['messageCounter'];
    }

    public function onUpdateNewMessage(array $update) {
        $this->messageCounter++;
    }
}

$settings = (new \danog\MadelineProto\Settings\Database\Mysql)
    ->setUri('tcp://localhost')
    ->setPassword('pass');

MyEventHandler::startAndLoop('bot.madeline', $settings);

This will automatically store the $messageCounter property in the MySQL/postgres/redis database.

The property can have any type (array, object, string, etc): there are no limits.

If you actually want to interact with a real database using SQL queries, use the amphp/mysql library.

How do I use threads in MadelineProto?

You can fork a new green thread using this code:

\danog\MadelineProto\Tools::callFork(function() {
    // Code to execute in forked thread
});
// Code to execute in original thread

Make sure to never use blocking functions in the forked thread (NO file_get_contents, PDO), only use async amphp libraries (i.e. amphp/file, amphp/mysql, and so on…).

See the async docs » for more info.

What is the “MadelineProto worker” process, can I kill it?

No, you must never kill it.

The MadelineProto worker process is like apache2: it keeps running in the background, waiting for incoming requests from MadelineProto.

Don’t kill it, or else MadelineProto will take 30+ seconds to start, every time you make a request.

You don’t kill your apache2/nginx webserver just because there are no incoming requests, and the same goes for the MadelineProto worker process.

When there are no incoming requests, CPU usage is extremely low (~0%), and RAM usage can be reduced by using the database (don’t forget to use updateSettings to update the settings).

What is the “This peer is not present in the internal peer database” error (also known as PeerNotInDbException)?

This error indicates that a specified peer (user, chat, channel) was not found in the internal MadelineProto peer database.

This can be because the user(bot) has never seen the peer before in the dialog list or in a chat.

This error can also be caused by an invalid ID, extracted manually from an update, instead of using the correct $this->getID($update) function.

This error can also be caused by referring to a user/chat/channel by its bot API ID, only if the (user)bot has never seen the peer before.
In this case, resolving a user/chat/channel @username with getInfo or importing an invite link with messages.importChatInvite, or (for users) enabling the setCacheAllPeersOnStartup setting will automatically cache the peer into the database, allowing you to use the bot API ID again.

Next section