Error cannot enqueue handshake after invoking quit

I have implemented the following code: module.exports = { getDataFromUserGps: function(callback) { connection.connect(); connection.query("SELECT * FROM usergps", ...

According to:

TL;DR You need to establish a new connection by calling the createConnection method after every disconnection.

and

Note: If you’re serving web requests, then you shouldn’t be ending connections on every request. Just create a connection on server
startup and use the connection/client object to query all the time.
You can listen on the error event to handle server disconnection and
for reconnecting purposes. Full code
here.


From:

  • Readme.md — Server disconnects:

    https://github.com/felixge/node-mysql#server-disconnects

It says:

Server disconnects

You may lose the connection to a MySQL server due to network problems,
the server timing you out, or the server crashing. All of these events
are considered fatal errors, and will have the err.code =
'PROTOCOL_CONNECTION_LOST'
. See the Error
Handling section for more information.

The best way to handle such unexpected disconnects is shown below:

function handleDisconnect(connection) {
  connection.on('error', function(err) {
    if (!err.fatal) {
      return;
    }

    if (err.code !== 'PROTOCOL_CONNECTION_LOST') {
      throw err;
    }

    console.log('Re-connecting lost connection: ' + err.stack);

    connection = mysql.createConnection(connection.config);
    handleDisconnect(connection);
    connection.connect();
  });
}

handleDisconnect(connection);

As you can see in the example above, re-connecting a connection is
done by establishing a new connection. Once terminated, an existing
connection object cannot be re-connected by design.

With Pool, disconnected connections will be removed from the pool
freeing up space for a new connection to be created on the next
getConnection call.


I have tweaked the function such that every time a connection is needed, an initializer function adds the handlers automatically:

function initializeConnection(config) {
    function addDisconnectHandler(connection) {
        connection.on("error", function (error) {
            if (error instanceof Error) {
                if (error.code === "PROTOCOL_CONNECTION_LOST") {
                    console.error(error.stack);
                    console.log("Lost connection. Reconnecting...");

                    initializeConnection(connection.config);
                } else if (error.fatal) {
                    throw error;
                }
            }
        });
    }

    var connection = mysql.createConnection(config);

    // Add handlers.
    addDisconnectHandler(connection);

    connection.connect();
    return connection;
}

Initializing a connection:

var connection = initializeConnection({
    host: "localhost",
    user: "user",
    password: "password"
});

Minor suggestion: This may not apply to everyone but I did run into a minor issue relating to scope. If the OP feels this edit was unnecessary then he/she can choose to remove it. For me, I had to change a line in initializeConnection, which was var connection = mysql.createConnection(config); to simply just

connection = mysql.createConnection(config);

The reason being that if connection is a global variable in your program, then the issue before was that you were making a new connection variable when handling an error signal. But in my nodejs code, I kept using the same global connection variable to run queries on, so the new connection would be lost in the local scope of the initalizeConnection method. But in the modification, it ensures that the global connection variable is reset This may be relevant if you’re experiencing an issue known as

Cannot enqueue Query after fatal error

after trying to perform a query after losing connection and then successfully reconnecting. This may have been a typo by the OP, but I just wanted to clarify.

TL;DR You need to establish a new connection by calling the createConnection method after every disconnection.

I was using the popular Mysql module for Node.js which is node-mysql and everytime, after the first page load was encountering a weird error with full stack trace.

What’s the one thing every developer wants? More screens! Enhance your coding experience with an external monitor to increase screen real estate.

Error: Cannot enqueue Handshake after invoking quit.
    at Protocol._validateEnqueue ......
    ...
    ...

Basically, the problem is that, if you’ve terminated an existing connection object then that cannot be re-connected afterwards.

So the solution is to call the createConnection method (followed by connect()) to create a new connection whenever you have terminated the old/existing connection.

If you’re using the node-postgres module for postgresql support in Node, then you’ll have to do something similar, i.e., call the connect method with the connection string to create new connections if you terminate the old connection (during the previous process/request) by calling pg.end() or client.end().

Note: If you’re serving web requests, then you shouldn’t be ending connections on every request. Just create a connection on server startup and use the connection/client object to query all the time. You can listen on the error event to handle server disconnection and for reconnecting purposes. Full code here.

You can do something similar with the postgres module’s clients if you’re creating them manually using pg.Client. Although when using the built-in pool approach to serve web requests, call pg.connect() on every request and you should be fine. Just make sure you’ve attached an event handler on the error event to prevent Node from crashing if the postgres server stops/restarts for some reason.

Calling pg.connect() will retrieve an existing pooled client or create a new one ONLY if all the pooled clients are busy and the pool is NOT full.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download

Код:

var sql = require("mysql");
var connection = sql.createConnection({
    host: 'localhost',
    user: 'root',
    password: 'password',
    database: 'chat'
});

app.get('/', function(req, res) {
    connection.connect();
    var loga = "kulonful";
    connection.query('select * from users where login = "'+loga+'"', function(err, result){
        if(err) { connection.end(); res.send('Произошла критическая ошибка'); }
        connection.end();
        res.send(result);
    });
})

В первый раз всё гладенько, а если обновить страницу — в консоли выбивает ошибку:

events.js:160
throw er; // Unhandled ‘error’ event
^

Error: Cannot enqueue Handshake after invoking quit.
at Protocol._validateEnqueue (/root/node_modules/mysql/lib/protocol/Protocol.js:202:16)
at Protocol._enqueue (/root/node_modules/mysql/lib/protocol/Protocol.js:135:13)
at Protocol.handshake (/root/node_modules/mysql/lib/protocol/Protocol.js:52:41)
at Connection.connect (/root/node_modules/mysql/lib/Connection.js:130:18)
at /root/api.js:18:16
at Layer.handle [as handle_request] (/root/node_modules/express/lib/router/layer.js:82:5)
at next (/root/node_modules/express/lib/router/route.js:100:13)
at Route.dispatch (/root/node_modules/express/lib/router/route.js:81:3)
at Layer.handle [as handle_request] (/root/node_modules/express/lib/router/layer.js:82:5)
at /root/node_modules/express/lib/router/index.js:235:24

Что не так? Помогите)

module.exports = {
    getDataFromUserGps: function(callback)
    {
        connection.connect();
        connection.query("SELECT * FROM usergps", 
            function(err, results, fields) {
                if (err) return callback(err, null);
                return callback(null, results);
            }
        ); 
        connection.end();
    },
    loginUser: function(login, pass, callback)
    {
        connection.connect();
        connection.query(
            "SELECT id FROM users WHERE login = ?AND pass = ?",
            [login, pass],
            function(err, results, fields) 
            {
                if (err) return callback(err, null);
                return callback(null, results);
            }
        ); 
        connection.end();
    },
    getUserDetails: function(userid, callback)
    {
        connection.connect();
        connection.query(
            "SELECT * FROM userProfilDetails LEFT JOIN tags ON userProfilDetails.userId = tags.userId WHERE userProfilDetails.userid = ?",
            [userid],
            function(err, results, fields)
            {
                if (err) return callback(err, null);
                return callback(null, results);
            }
        );
        connection.end();
    },
    addTags: function(userId, tags)
    {
        connection.connect();
        connection.query(
            "INSERT INTO tag (userId, tag) VALUES (?, ?)",
            [userId, tags],
            function(err, results, fields)
            {
                if (err) throw err;
            }
        )
        connection.end();
    }
}

Everything worked fine at first, but when I executed the second “query, “I got this error:

Cannot enqueue Handshake after invoking quit

I’ve tried turning off the connection without using the.end() method, but it doesn’t work.
Thanked first.
Radex
Those blind solutions and water paste I will not translate.
According to:
Fixing Node Mysql “Error: Cannot enqueue Handshake after invoking quit.”:
http://codetheory.in/fixing-node-mysql-error-cannot-enqueue-handshake-after-invoking-quit/

TL; Every time DR closes a connection you need to create a new connection using the createConnection method.
And
Note: If you are serving web requests, you should not turn off the connection each time the request is processed. When the server starts up, create a connection and keep querying it with the Connection/Client object. To handle server disconnection and reconnection events you can listen for error events. Complete code: Here.
Again according to:
The Readme. Md – Server disconnects:
https://github.com/felixge/node-mysql#server-disconnects
It said

Server disconnects
You may lose your connection to MySQL server due to a network problem, server timeout, or server hanging. All of these are considered “fatal errors “and there will be an error code err. Code = 'PROTOCOL_CONNECTION_LOST'. See the error handling section for more information.
The best way to handle these unwanted disconnections is as follows:

function handleDisconnect(connection) {
  connection.on('error', function(err) {
    if (!err.fatal) {
      return;
    }

    if (err.code !== 'PROTOCOL_CONNECTION_LOST') {
      throw err;
    }

    console.log('Re-connecting lost connection: ' + err.stack);

    connection = mysql.createConnection(connection.config);
    handleDisconnect(connection);
    connection.connect();
  });
}

handleDisconnect(connection);

As the example above shows, reconnection is achieved by creating a new connection, because the connection object is designed so that it cannot be reconnected once it dies.
When a connection pool is used, suspended connections are removed from the pool and space is freed, and a new connection is automatically created when a new connection request arrives.
the respondent has posted his own autoreconnect code at the end, so I’m not going to post it here.

The answer was 18:58 on May 3, 2013
XP1
Although this answer was not adopted by the main topic, but I and the following comments have always thought that this answer is better.
The original web site: http://stackoverflow.com/questions/14087924/cannot-enqueue-handshake-after-invoking-quit

var Winston           = require('winston'); // For logging
var SteamUser         = require('steam-user'); // The heart of the bot.  We'll write the soul ourselves.
var TradeOfferManager = require('steam-tradeoffer-manager'); // Only required if you're using trade offers
var config            = require('./config.js');
var fs                = require('fs'); // For writing a dope-ass file for TradeOfferManager
var mysql             = require('mysql');
var market            = require('steam-market-pricing');


var appid = {
    TF2:   440,
    DOTA2: 570,
    CSGO:  730,
    Steam: 753
};

var contextid = {
    TF2:   2,
    DOTA2: 2,
    CSGO:  2,
    Steam: 6
};



var logger = new (Winston.Logger)({
        transports: [
            new (Winston.transports.Console)({
                colorize: true, 
                level: 'debug'
            }),
            new (Winston.transports.File)({
                level: 'info', 
                timestamp: true, 
                filename: 'cratedump.log', 
                json: false
            })
        ]
});

// Initialize the Steam client and our trading library
var client = new SteamUser();
var offers = new TradeOfferManager({
    steam:        client,
    domain:       config.domain, 
    language:     "en", // English item descriptions
    pollInterval: 10000, // (Poll every 10 seconds (10,000 ms)
    cancelTime:   300000 // Expire any outgoing trade offers that have been up for 5+ minutes (300,000 ms)
});

client.logOn({
    accountName: config.username,
    password: config.password
});

client.on('loggedOn', function (details) {
    logger.info("Logged into Steam as " + client.steamID.getSteamID64());
});

client.on('error', function (e) {
    logger.error(e);
    process.exit(1);
});

client.on('webSession', function (sessionID, cookies) {
    logger.debug("Got web session");
    // Set our status to "Online" (otherwise we always appear offline)
    client.friends.setPersonaState(SteamUser.Steam.EPersonaState.Online);
    offers.setCookies(cookies, function (err){
        if (err) {
            logger.error('Unable to set trade offer cookies: '+err);
            process.exit(1); // No point in staying up if we can't use trade offers
        }
        logger.debug("Trade offer cookies set.  Got API Key: "+offers.apiKey);
    });
});

client.on('accountLimitations', function (limited, communityBanned, locked, canInviteFriends) {
    if (limited) {
        logger.warn("Our account is limited. We cannot send friend invites, use the market, open group chat, or access the web API.");
    }
    if (communityBanned){
        logger.warn("Our account is banned from Steam Community");
    }
    if (locked){
        logger.error("Our account is locked. We cannot trade/gift/purchase items, play on VAC servers, or access Steam Community.  Shutting down.");
        process.exit(1);
    }
    if (!canInviteFriends){
        logger.warn("Our account is unable to send friend requests.");
    }
});

offers.on('newOffer', function(offer) {
  var steamAccountID64 = offer.partner.getSteamID64();

  var connection = mysql.createConnection({
    host: '***********',
    user: '***********',
    password: '**********',
    database: '*************'
  });

    connection.query('SELECT COUNT(*) AS Total FROM incomingPlayers WHERE accountID=' + steamAccountID64, function(err, rows, fields) {


    if (rows[0].Total == 0) {

      if (offer.partner.getSteamID64() === config.admin || offer.itemsToGive.length === 0) {
        console.log(steamAccountID64);
        offer.accept(function(err) {
          if (err) {
            logger.error("Unable to accept offer " + offer.id + ": " + err.message);
          } else {
            logger.info("Offer accepted");
          }
        });

        var numberofitems = offer.itemsToReceive.length;

        for (var i = 0; i < numberofitems; i++) {

          if (offer.itemsToReceive[i].appid == "730") {

            var itemInfo = {
              itemName: offer.itemsToReceive[i].market_hash_name,
              assetID: offer.itemsToReceive[i].assetid,
              iconURL: offer.itemsToReceive[i].icon_url,
              accountID: steamAccountID64
            };

            connection.query('INSERT INTO incomingOffers SET ?', itemInfo);

            market.getItemPrice(730, 'MP9 | Storm (Minimal Wear)', function(err, data) {
                    connection.query("UPDATE incomingOffers SET itemValue='" + data.lowest_price.replace('$','') + "' WHERE assetID='4361351533'");
            });

            console.log(itemInfo.itemName + " of ID:" + itemInfo.assetID + " was accepted for trade by user : " + steamAccountID64);


          } else {
            console.log("Attempted to add item of appid: " + offer.itemsToReceive[i].appid);
          };

        };

        connection.query('INSERT INTO incomingPlayers SET ?', {
          accountID: steamAccountID64,
          itemCount: numberofitems
        });

      } else {

        offer.decline(function(err) {
          if (err) {
            logger.error("Unable to decline offer " + offer.id + ": " + err.message);
          } else {
            console.log("Trade was declined from " + offer.partner.getSteamID64() + ", user is not admin or sent dodgy offer");
          };
        });
      };
    } else {
      offer.decline(function(err) {
        if (err) {
          logger.error("Unable to decline offer " + offer.id + ": " + err.message);
        } else {
          console.log("Trade was declined from " + offer.partner.getSteamID64() + ", user already went in");
        };
      });

    };

  connection.end();
  });

});

I had the same problem and Google led me here. I agree with @Ata that it’s not right to just remove end(). After further Googling, I think using pooling is a better way.

node-mysql doc about pooling

It’s like this:

var mysql = require('mysql');
var pool  = mysql.createPool(...);

pool.getConnection(function(err, connection) {
    connection.query( 'bla bla', function(err, rows) {
        connection.release();
    });
});

According to:

TL;DR You need to establish a new connection by calling the createConnection method after every disconnection.

and

Note: If you’re serving web requests, then you shouldn’t be ending connections on every request. Just create a connection on server
startup and use the connection/client object to query all the time.
You can listen on the error event to handle server disconnection and
for reconnecting purposes. Full code
here.


From:

  • Readme.md — Server disconnects:

    https://github.com/felixge/node-mysql#server-disconnects

It says:

Server disconnects

You may lose the connection to a MySQL server due to network problems,
the server timing you out, or the server crashing. All of these events
are considered fatal errors, and will have the err.code =
'PROTOCOL_CONNECTION_LOST'
. See the Error
Handling section for more information.

The best way to handle such unexpected disconnects is shown below:

function handleDisconnect(connection) {
  connection.on('error', function(err) {
    if (!err.fatal) {
      return;
    }

    if (err.code !== 'PROTOCOL_CONNECTION_LOST') {
      throw err;
    }

    console.log('Re-connecting lost connection: ' + err.stack);

    connection = mysql.createConnection(connection.config);
    handleDisconnect(connection);
    connection.connect();
  });
}

handleDisconnect(connection);

As you can see in the example above, re-connecting a connection is
done by establishing a new connection. Once terminated, an existing
connection object cannot be re-connected by design.

With Pool, disconnected connections will be removed from the pool
freeing up space for a new connection to be created on the next
getConnection call.


I have tweaked the function such that every time a connection is needed, an initializer function adds the handlers automatically:

function initializeConnection(config) {
    function addDisconnectHandler(connection) {
        connection.on("error", function (error) {
            if (error instanceof Error) {
                if (error.code === "PROTOCOL_CONNECTION_LOST") {
                    console.error(error.stack);
                    console.log("Lost connection. Reconnecting...");

                    initializeConnection(connection.config);
                } else if (error.fatal) {
                    throw error;
                }
            }
        });
    }

    var connection = mysql.createConnection(config);

    // Add handlers.
    addDisconnectHandler(connection);

    connection.connect();
    return connection;
}

Initializing a connection:

var connection = initializeConnection({
    host: "localhost",
    user: "user",
    password: "password"
});

Minor suggestion: This may not apply to everyone but I did run into a minor issue relating to scope. If the OP feels this edit was unnecessary then he/she can choose to remove it. For me, I had to change a line in initializeConnection, which was var connection = mysql.createConnection(config); to simply just

connection = mysql.createConnection(config);

The reason being that if connection is a global variable in your program, then the issue before was that you were making a new connection variable when handling an error signal. But in my nodejs code, I kept using the same global connection variable to run queries on, so the new connection would be lost in the local scope of the initalizeConnection method. But in the modification, it ensures that the global connection variable is reset This may be relevant if you’re experiencing an issue known as

Cannot enqueue Query after fatal error

after trying to perform a query after losing connection and then successfully reconnecting. This may have been a typo by the OP, but I just wanted to clarify.

If you using the node-mysql module, just remove the .connect and .end. Just solved the problem myself. Apparently they pushed in unnecessary code in their last iteration that is also bugged. You don’t need to connect if you have already ran the createConnection call

Do not connect() and end() inside the function. This will cause problems on repeated calls to the function. Make the connection only

var connection = mysql.createConnection({
      host: 'localhost',
      user: 'node',
      password: 'node',
      database: 'node_project'
    })

connection.connect(function(err) {
    if (err) throw err

});

once and reuse that connection.

Inside the function

function insertData(name,id) {

  connection.query('INSERT INTO members (name, id) VALUES (?, ?)', [name,id], function(err,result) {
      if(err) throw err
  });


}

According to:

TL;DR You need to establish a new connection by calling the createConnection method after every disconnection.

and

Note: If you’re serving web requests, then you shouldn’t be ending connections on every request. Just create a connection on server
startup and use the connection/client object to query all the time.
You can listen on the error event to handle server disconnection and
for reconnecting purposes. Full code
here.


From:

  • Readme.md — Server disconnects:

    https://github.com/felixge/node-mysql#server-disconnects

It says:

Server disconnects

You may lose the connection to a MySQL server due to network problems,
the server timing you out, or the server crashing. All of these events
are considered fatal errors, and will have the err.code =
'PROTOCOL_CONNECTION_LOST'
. See the Error
Handling section for more information.

The best way to handle such unexpected disconnects is shown below:

function handleDisconnect(connection) {
  connection.on('error', function(err) {
    if (!err.fatal) {
      return;
    }

    if (err.code !== 'PROTOCOL_CONNECTION_LOST') {
      throw err;
    }

    console.log('Re-connecting lost connection: ' + err.stack);

    connection = mysql.createConnection(connection.config);
    handleDisconnect(connection);
    connection.connect();
  });
}

handleDisconnect(connection);

As you can see in the example above, re-connecting a connection is
done by establishing a new connection. Once terminated, an existing
connection object cannot be re-connected by design.

With Pool, disconnected connections will be removed from the pool
freeing up space for a new connection to be created on the next
getConnection call.


I have tweaked the function such that every time a connection is needed, an initializer function adds the handlers automatically:

function initializeConnection(config) {
    function addDisconnectHandler(connection) {
        connection.on("error", function (error) {
            if (error instanceof Error) {
                if (error.code === "PROTOCOL_CONNECTION_LOST") {
                    console.error(error.stack);
                    console.log("Lost connection. Reconnecting...");

                    initializeConnection(connection.config);
                } else if (error.fatal) {
                    throw error;
                }
            }
        });
    }

    var connection = mysql.createConnection(config);

    // Add handlers.
    addDisconnectHandler(connection);

    connection.connect();
    return connection;
}

Initializing a connection:

var connection = initializeConnection({
    host: "localhost",
    user: "user",
    password: "password"
});

Minor suggestion: This may not apply to everyone but I did run into a minor issue relating to scope. If the OP feels this edit was unnecessary then he/she can choose to remove it. For me, I had to change a line in initializeConnection, which was var connection = mysql.createConnection(config); to simply just

connection = mysql.createConnection(config);

The reason being that if connection is a global variable in your program, then the issue before was that you were making a new connection variable when handling an error signal. But in my nodejs code, I kept using the same global connection variable to run queries on, so the new connection would be lost in the local scope of the initalizeConnection method. But in the modification, it ensures that the global connection variable is reset This may be relevant if you’re experiencing an issue known as

Cannot enqueue Query after fatal error

after trying to perform a query after losing connection and then successfully reconnecting. This may have been a typo by the OP, but I just wanted to clarify.

В соответствии с:

TL, д-р Вам необходимо установить новое соединение, позвонив в createConnection метод после каждого отключения.

и

Примечание: Если вы обслуживаете веб-запросы, вам не следует прерывать соединения при каждом запросе. Просто создайте соединение при запуске сервера и используйте объект соединения/клиента для постоянного запроса. Вы можете прослушивать событие ошибки, чтобы обработать отключение сервера и повторное подключение. Полный код
здесь.


От:

  • Readme.md — Сервер отключается:

    https://github.com/felixge/node-mysql#server-disconnects

В нем говорится:

Сервер отключается

Вы можете потерять соединение с сервером MySQL из-за проблем с сетью, таймаута сервера или сбоя сервера. Все эти события считаются фатальными ошибками и будут иметь err.code =
'PROTOCOL_CONNECTION_LOST'
. Дополнительные сведения см. в разделе «Обработка ошибок».

Лучший способ справиться с такими неожиданными отключениями показан ниже:

function handleDisconnect(connection) {
  connection.on('error', function(err) {
    if (!err.fatal) {
      return;
    }

    if (err.code !== 'PROTOCOL_CONNECTION_LOST') {
      throw err;
    }

    console.log('Re-connecting lost connection: ' + err.stack);

    connection = mysql.createConnection(connection.config);
    handleDisconnect(connection);
    connection.connect();
  });
}

handleDisconnect(connection);

Как видно из приведенного выше примера, повторное подключение выполняется путем установления нового подключения. После завершения существующий объект соединения не может быть повторно подключен по замыслу.

С помощью пула отключенные соединения будут удалены из пула, освобождая место для нового соединения, которое будет создано при следующем вызове getConnection.


Я настроил функцию таким образом, чтобы каждый раз, когда требуется соединение, функция инициализатора автоматически добавляла обработчики:

function initializeConnection(config) {
    function addDisconnectHandler(connection) {
        connection.on("error", function (error) {
            if (error instanceof Error) {
                if (error.code === "PROTOCOL_CONNECTION_LOST") {
                    console.error(error.stack);
                    console.log("Lost connection. Reconnecting...");

                    initializeConnection(connection.config);
                } else if (error.fatal) {
                    throw error;
                }
            }
        });
    }

    var connection = mysql.createConnection(config);

    // Add handlers.
    addDisconnectHandler(connection);

    connection.connect();
    return connection;
}

Инициализация соединения:

var connection = initializeConnection({
    host: "localhost",
    user: "user",
    password: "password"
});

Незначительное предложение: Это может относиться не ко всем, но я столкнулся с небольшой проблемой, связанной с областью действия. Если ОП считает, что это редактирование было ненужным, он / она может удалить его. Для меня мне пришлось изменить строку в initializeConnection, который был var connection = mysql.createConnection(config); просто просто

connection = mysql.createConnection(config);

Причина в том, что если connection является глобальной переменной в вашей программе, то раньше проблема заключалась в том, что вы создавали новый connection переменная при обработке сигнала ошибки. Но в моем коде nodejs я продолжал использовать один и тот же глобальный connection переменная для выполнения запросов, поэтому новый connection будет потерян в локальном масштабе initalizeConnection метод. Но в модификации он гарантирует, что глобальный connection переменная сбрасывается Это может иметь значение, если вы столкнулись с проблемой, известной как

Не удается поставить запрос после фатальной ошибки

после попытки выполнить запрос после потери соединения, а затем успешного повторного подключения. Возможно, это была опечатка ОП, но я просто хотел уточнить.

Понравилась статья? Поделить с друзьями:
  • Error cannot enqueue handshake after already enqueuing a handshake
  • Error cannot determine path to tools jar library for 16
  • Error cannot delete branch test checked out at
  • Error cannot delete branch master checked out at
  • Error cannot delete branch main checked out at