SPIFFS Always Crashing after doing OTA

So i am using ESP32 to implement ota using tinygsm.


#include <Update.h>
#define TINY_GSM_MODEM_SIM800
// Increase RX buffer
#define TINY_GSM_RX_BUFFER 1024

const char apn[] = "Internet";
const char user[] = "";
const char pass[] = "";




#define SerialAT  Serial2

#include <TinyGsmClient.h>
#include <CRC32.h>
#include "FS.h"
#include "SPIFFS.h"
#define DUMP_AT_COMMANDS
#ifdef DUMP_AT_COMMANDS
#include <StreamDebugger.h>
StreamDebugger debugger(SerialAT, Serial);
TinyGsm modem(debugger);
#else
TinyGsm modem(SerialAT);
#endif


TinyGsmClient client(modem);

const char server[] = "myServer.com";
const int port = 80;
const char resource[] = "/firmware.bin"; //here de bin file

uint32_t knownCRC32 =0xaf968d0e ;
uint32_t knownFileSize = 938256; // In case server does not send it


void printPercent(uint32_t readLength, uint32_t contentLength);
void listDir(fs::FS &fs, const char *dirname, uint8_t levels);
void updateFromFS();
void performUpdate(Stream &updateSource, size_t updateSize);

void setup()
{
    SerialAT.begin(9600, SERIAL_8N1, 15, 14);
    // Set console baud rate
    Serial.begin(115200);

    // setupModem();
    delay(10);

    if (!SPIFFS.begin(true))
    {
        Serial.println("SPIFFS Mount Failed");
        return;
    }
    SPIFFS.format();
    listDir(SPIFFS, "/", 0);

    // Set GSM module baud rate
    
    delay(3000);

    // Restart takes quite some time
    // To skip it, call init() instead of restart()
    Serial.println("Initializing modem...");
    modem.restart();

    String modemInfo = modem.getModemInfo();
    Serial.print("Modem: ");
    Serial.println(modemInfo);

    // Unlock your SIM card with a PIN
    //modem.simUnlock("1234");
}



void loop()
{
    Serial.print("Waiting for network...");
    if (!modem.waitForNetwork())
    {
        Serial.println(" fail");
        delay(10000);
        return;
    }
    Serial.println(" OK");

    Serial.print("Connecting to ");
    Serial.print(apn);
    if (!modem.gprsConnect(apn, user, pass))
    {
        Serial.println(" fail");
        delay(10000);
        return;
    }
    Serial.println(" OK");

    Serial.print("Connecting to ");
    Serial.print(server);

    // if you get a connection, report back via serial:
    if (!client.connect(server, port))
    {
        Serial.println(" fail");
        delay(10000);
        return;
    }
    Serial.println(" OK");
    
    // Make a HTTP request:
    client.print(String("GET ") + resource + " HTTP/1.0\r\n");
    client.print(String("Host: ") + server + "\r\n");
    client.print("Connection: close\r\n\r\n");

    long timeout = millis();
    while (client.available() == 0)
    {
        if (millis() - timeout > 5000L)
        {
            Serial.println(">>> Client Timeout !");
            client.stop();
            delay(10000L);
            return;
        }
    }

    Serial.println("Reading header");
    uint32_t contentLength = knownFileSize;

    File file = SPIFFS.open("/update.bin", FILE_APPEND);


    while (client.available())
    {
        String line = client.readStringUntil('\n');
        line.trim();
        //Serial.println(line);    // Uncomment this to show response header
        line.toLowerCase();
        if (line.startsWith("content-length:"))
        {
            contentLength = line.substring(line.lastIndexOf(':') + 1).toInt();
        }
        else if (line.length() == 0)
        {
            break;
        }
    }


    timeout = millis();
    uint32_t readLength = 0;
    CRC32 crc;

    unsigned long timeElapsed = millis();
    delay(500);
    printPercent(readLength, contentLength);
    delay(500);

    while (readLength < contentLength && client.connected() && millis() - timeout < 10000L)
    {
        int i = 0;
        while (client.available())
        {
                // read file data to spiffs
            if (!file.print(char(client.read())))
            {
                Serial.println("Appending file");
            }
            //Serial.print((char)c);       // Uncomment this to show data
            //crc.update(c);
            readLength++;

            if (readLength % (contentLength / 13) == 0)
            {
                printPercent(readLength, contentLength);
            }
            timeout = millis();
        }
    }

    file.close();

    printPercent(readLength, contentLength);
    timeElapsed = millis() - timeElapsed;
    Serial.println();

    client.stop();
    Serial.println("stop client");

    modem.gprsDisconnect();
    Serial.println("gprs disconnect");
    Serial.println();

    float duration = float(timeElapsed) / 1000;

    Serial.print("File Size ");
    Serial.println(contentLength);
    Serial.print("Length:  ");
    Serial.println(readLength);
    Serial.print("Calculated. CRC32:    0x");
    Serial.println(crc.finalize(), HEX);
    Serial.print("Expected CRC32:    0x");
    Serial.println(knownCRC32, HEX);
    Serial.print("Downloaded in:       ");
    Serial.print(duration);
    Serial.println("s");

    Serial.println("Wait for 3 seconds");
    for (int i = 0; i < 3; i++)
    {
        Serial.print(String(i) + "...");
        delay(1000);
    }
  
    //readFile(SPIFFS, "/update.bin");

    updateFromFS();

    // Do nothing forevermore
    while (true)
    {
        delay(1000);
    }
}







void appendFile(fs::FS &fs, const char *path, const char *message)
{
    Serial.printf("Appending to file: %s\n", path);

    File file = fs.open(path, FILE_APPEND);
    if (!file)
    {
        Serial.println("Failed to open file for appending");
        return;
    }
    if (file.print(message))
    {
        Serial.println("APOK");
    }
    else
    {
        Serial.println("APX");
    }
}

void readFile(fs::FS &fs, const char *path)
{
    Serial.printf("Reading file: %s\n", path);

    File file = fs.open(path);
    if (!file || file.isDirectory())
    {
        Serial.println("Failed to open file for reading");
        return;
    }

    Serial.print("Read from file: ");
    while (file.available())
    {
        Serial.write(file.read());
        delayMicroseconds(100);
    }
}

void writeFile(fs::FS &fs, const char *path, const char *message)
{
    Serial.printf("Writing file: %s\n", path);

    File file = fs.open(path, FILE_WRITE);
    if (!file)
    {
        Serial.println("Failed to open file for writing");
        return;
    }
    if (file.print(message))
    {
        Serial.println("File written");
    }
    else
    {
        Serial.println("Write failed");
    }
}

void listDir(fs::FS &fs, const char *dirname, uint8_t levels)
{
    Serial.printf("Listing directory: %s\n", dirname);

    File root = fs.open(dirname);
    if (!root)
    {
        Serial.println("Failed to open directory");
        return;
    }
    if (!root.isDirectory())
    {
        Serial.println("Not a directory");
        return;
    }

    File file = root.openNextFile();
    while (file)
    {
        if (file.isDirectory())
        {
            Serial.print("  DIR : ");
            Serial.println(file.name());
            if (levels)
            {
                listDir(fs, file.name(), levels - 1);
            }
        }
        else
        {
            Serial.print("  FILE: ");
            Serial.print(file.name());
            Serial.print("  SIZE: ");
            Serial.println(file.size());
        }
        file = root.openNextFile();
    }
}

void deleteFile(fs::FS &fs, const char *path)
{
    Serial.printf("Deleting file: %s\n", path);
    if (fs.remove(path))
    {
        Serial.println("File deleted");
    }
    else
    {
        Serial.println("Delete failed");
    }
}

void updateFromFS()
{
    File updateBin = SPIFFS.open("/update.bin");
    if (updateBin)
    {
        if (updateBin.isDirectory())
        {
            Serial.println("Directory error");
            updateBin.close();
            return;
        }

        size_t updateSize = updateBin.size();

        if (updateSize > 0)
        {
            Serial.println("Starting update");
            performUpdate(updateBin, updateSize);
        }
        else
        {
            Serial.println("Error, archivo vacío");
        }

        updateBin.close();

        // whe finished remove the binary from sd card to indicate end of the process
        //fs.remove("/update.bin");
    }
    else
    {
        Serial.println("no such binary");
    }
}

void performUpdate(Stream &updateSource, size_t updateSize)
{
    if (Update.begin(updateSize))
    {
        size_t written = Update.writeStream(updateSource);
        if (written == updateSize)
        {
            Serial.println("Writes : " + String(written) + " successfully");
        }
        else
        {
            Serial.println("Written only : " + String(written) + "/" + String(updateSize) + ". Retry?");
        }
        if (Update.end())
        {
            Serial.println("OTA finished!");
            if (Update.isFinished())
            {
                Serial.println("Restart ESP device!");
                ESP.restart();
            }
            else
            {
                Serial.println("OTA not fiished");
            }
        }
        else
        {
            Serial.println("Error occured #: " + String(Update.getError()));
        }
    }
    else
    {
        Serial.println("Cannot beggin update");
    }
}





void printPercent(uint32_t readLength, uint32_t contentLength)
{
    // If we know the total length
    if (contentLength != -1)
    {
        Serial.print("\r ");
        Serial.print((100.0 * readLength) / contentLength);
        Serial.print('%');
    }
    else
    {
        Serial.println(readLength);
    }
}



// void setupModem()
// {
// #ifdef MODEM_RST
//     // Keep reset high
//     pinMode(MODEM_RST, OUTPUT);
//     digitalWrite(MODEM_RST, HIGH);
// #endif

//     pinMode(MODEM_PWRKEY, OUTPUT);
//     pinMode(MODEM_POWER_ON, OUTPUT);

//     // Turn on the Modem power first
//     digitalWrite(MODEM_POWER_ON, HIGH);

//     // Pull down PWRKEY for more than 1 second according to manual requirements
//     digitalWrite(MODEM_PWRKEY, HIGH);
//     delay(100);
//     digitalWrite(MODEM_PWRKEY, LOW);
//     delay(1000);
//     digitalWrite(MODEM_PWRKEY, HIGH);

//     // Initialize the indicator as an output
//     pinMode(LED_GPIO, OUTPUT);
//     digitalWrite(LED_GPIO, LED_OFF);
// }

and after that the code that has been get via ota running well.
So because it successfull i want to assemble it with my mqtt codes. And then after i upload it. it display a crash error message like this

Leaving...
Hard resetting via RTS pin...
--- Terminal on COM8 | 115200 8-N-1
--- Available filters and text transformations: colorize, debug, default, direct, esp32_exception_decoder, hexlify, log2file, nocontrol, printable, send_on_enter, time
--- More details at https://bit.ly/pio-monitor-filters
--- Quit: Ctrl+C | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H
�␌��d������)}�r�'��0��E�ٺ�A�)�0%�v'��0,��␅�v������}d�W���j�[��iDR����f�V␚��c-"��:�C!�+�:��f�␖³b����L´C!��d'��00␓�0��+�:�fʲC!�+�:��0����b��:&�8C����� �Q0��ʥ�HWait...

assert failed: heap_caps_free heap_caps.c:360 (heap != NULL && "free() target pointer is outside heap areas")


Backtrace: 0x40083641:0x3ffb1f70 0x4008b789:0x3ffb1f90 0x400910a9:0x3ffb1fb0 0x40083afe:0x3ffb20e0 0x400910d9:0x3ffb2100 0x400dbfda:0x3ffb2120 0x400dbfe9:0x3ffb2140 0x400d5cff:0x3ffb2160 0x400d5e17:0x3ffb2200 0x400dd7ce:0x3ffb2290




ELF file SHA256: 17a81a0719d35c00

Rebooting...
ets Jun  8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0030,len:1184
load:0x40078000,len:13192
load:0x40080400,len:3028
entry 0x400805e4
Wait...

assert failed: heap_caps_free heap_caps.c:360 (heap != NULL && "free() target pointer is outside heap areas")


Backtrace: 0x40083641:0x3ffb1f70 0x4008b789:0x3ffb1f90 0x400910a9:0x3ffb1fb0 0x40083afe:0x3ffb20e0 0x400910d9:0x3ffb2100 0x400dbfda:0x3ffb2120 0x400dbfe9:0x3ffb2140 0x400d5cff:0x3ffb2160 0x400d5e17:0x3ffb2200 0x400dd7ce:0x3ffb2290




ELF file SHA256: 17a81a0719d35c00

Rebooting...
ets Jun  8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0030,len:1184
load:0x40078000,len:13192
load:0x40080400,len:3028
entry 0x400805e4
Wait...

assert failed: heap_caps_free heap_caps.c:360 (heap != NULL && "free() target pointer is outside heap areas")


Backtrace: 0x40083641:0x3ffb1f70 0x4008b789:0x3ffb1f90 0x400910a9:0x3ffb1fb0 0x40083afe:0x3ffb20e0 0x400910d9:0x3ffb2100 0x400dbfda:0x3ffb2120 0x400dbfe9:0x3ffb2140 0x400d5cff:0x3ffb2160 0x400d5e17:0x3ffb2200 0x400dd7ce:0x3ffb2290

Even after i rollback with the only mqtt code it always display this error, before i try the ota the code never get this problem.

It might be possible that when you uploaded the new version via Serial, it still runs off the OTA partition that has the faulty partition. Can you do Project tasks → Platform → Erase and then upload again?