В журнале моего скрипта для таблицы на Google Таблицах то и дело возникает эта ошибка:

Error fetching data for Modrinth project ID lhGA9TYQ: Exception: Request failed for https://api.modrinth.com returned code 500. Truncated server response: {"error":"database_error","description":"Database Error: Redis Pool Error: Error occurred while creating a new object: Cannot assign requested addr... (use muteHttpExceptions option to examine full response)

Как мне её исправить? Вот код моего скрипта:

function updateAllStats() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  const headerRow = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0];
  
  // Получаем индексы столбцов по названиям
  const columnIndices = {
    name: headerRow.indexOf('name') + 1,
    gameVer: headerRow.indexOf('gameVer') + 1,
    modrinthId: headerRow.indexOf('modrinthId') + 1,
    curseforgeId: headerRow.indexOf('curseforgeId') + 1,
    follows: headerRow.indexOf('follows') + 1,
    mrDownloads: headerRow.indexOf('mrDownloads') + 1,
    cfDownloads: headerRow.indexOf('cfDownloads') + 1,
    popularity: headerRow.indexOf('popularity') + 1,
    actualModVer: headerRow.indexOf('actualModVer') + 1
  };

  const lastRow = sheet.getLastRow();
  
  for (let row = 2; row <= lastRow; row++) {
    const modrinthId = sheet.getRange(row, columnIndices.modrinthId).getValue();
    const curseforgeId = sheet.getRange(row, columnIndices.curseforgeId).getValue();
    const gameVer = sheet.getRange(row, columnIndices.gameVer).getValue(); // Получаем gameVer

    Logger.log(`Processing row ${row}: Modrinth ID = ${modrinthId}, CurseForge ID = ${curseforgeId}, Game Version = ${gameVer}`);

    if ((modrinthId === false || modrinthId === "FALSE") && (curseforgeId === false || curseforgeId === "FALSE")) {
      Logger.log(`Skipping row ${row} due to both IDs being FALSE`);
      continue;
    }

    let follows = sheet.getRange(row, columnIndices.follows).getValue() || 0;
    let mrDownloads = sheet.getRange(row, columnIndices.mrDownloads).getValue() || 0;
    let cfDownloads = sheet.getRange(row, columnIndices.cfDownloads).getValue() || 0;
    let actualModVer = ''; // Инициализируем переменную для actualModVer

    // Получение статистики и актуальной версии для Modrinth
    if (modrinthId && modrinthId !== false && modrinthId !== "FALSE") {
      const modrinthData = fetchModrinthStats(modrinthId, gameVer);
      if (modrinthData.followersCount > 0) {
        follows = modrinthData.followersCount;
      }
      if (modrinthData.downloadsCount > 0) {
        mrDownloads = modrinthData.downloadsCount;
      }
      if (modrinthData.latestVersion) {
        actualModVer = modrinthData.latestVersion;
      }
      Logger.log(`Modrinth data for ID ${modrinthId}: Followers = ${modrinthData.followersCount}, Downloads = ${modrinthData.downloadsCount}, Latest Version = ${modrinthData.latestVersion}`);
    }
    
    // Если Modrinth не удалось получить версию, пробуем CurseForge
    if ((!actualModVer || actualModVer === '') && curseforgeId && curseforgeId !== false && curseforgeId !== "FALSE") {
      const cfData = fetchCurseForgeMod(curseforgeId);
      if (cfData.downloadCount > 0) {
        cfDownloads = cfData.downloadCount;
      }
      if (cfData.latestVersion) {
        actualModVer = cfData.latestVersion;
      }
      Logger.log(`CurseForge data for ID ${curseforgeId}: Downloads = ${cfData.downloadCount}, Latest Version = ${cfData.latestVersion}`);
    }

    // Обновляем значения в таблице
    sheet.getRange(row, columnIndices.mrDownloads).setValue(mrDownloads);
    sheet.getRange(row, columnIndices.follows).setValue(follows); 
    sheet.getRange(row, columnIndices.cfDownloads).setValue(cfDownloads);
    sheet.getRange(row, columnIndices.actualModVer).setValue(actualModVer); // Устанавливаем actualModVer

    const values = [follows, mrDownloads, cfDownloads];
    const nonZeroValues = values.filter(value => value > 0);
    let popularity = 0;

    if (nonZeroValues.length > 0) {
      popularity = nonZeroValues.reduce((acc, val) => acc + val, 0) / nonZeroValues.length;
    }
    
    Logger.log(`Calculated popularity for row ${row}: ${popularity}`);
    sheet.getRange(row, columnIndices.popularity).setValue(popularity);
  }

  sortByColumns(sheet, columnIndices.popularity, columnIndices.name);
}

function fetchModrinthStats(projectId, gameVerPrefix) {
  const url = `https://api.modrinth.com/v2/project/${projectId}`;
  try {
    const response = UrlFetchApp.fetch(url);
    const data = JSON.parse(response.getContentText());
    Logger.log(`Fetched data from Modrinth for ID ${projectId}`);
    
    // Получаем список версий проекта
    const versionsUrl = `https://api.modrinth.com/v2/project/${projectId}/version`;
    const versionsResponse = UrlFetchApp.fetch(versionsUrl);
    const versionsData = JSON.parse(versionsResponse.getContentText());

    // Фильтруем версии по gameVerPrefix
    const filteredVersions = versionsData.filter(version => {
      return version.game_versions.some(gv => gv.startsWith(String(gameVerPrefix)));
    });

    // Сортируем от современных к более старым по дате опубликования
    filteredVersions.sort((a, b) => new Date(b.date_published) - new Date(a.date_published));

    // Если есть версии после фильтрации, берем первую (самую новую)
    let latestVersion = '';
    if (filteredVersions.length > 0) {
      latestVersion = filteredVersions[0].version_number || '';
    }

    return {
      downloadsCount: data.downloads || 0,
      followersCount: data.followers || 0,
      latestVersion: latestVersion
    };
  } catch (error) {
    Logger.log(`Error fetching data for Modrinth project ID ${projectId}: ${error}`);
    return {
      downloadsCount: 0,
      followersCount: 0,
      latestVersion: ''
    };
  }
}

function fetchCurseForgeMod(projectId) {
  const apiKey = '$2a$10$Urj8j4d0C3ctaItu3WOUNex3LZJ2WBRj0q5mYojEpuGmjYZCUNas. '; // API Key
  const url = `https://api.curseforge.com/v1/mods/${projectId}`;
  const headers = {
    'Accept': 'application/json',
    'x-api-key': apiKey
  };

  try {
    const response = UrlFetchApp.fetch(url, { headers: headers });
    const data = JSON.parse(response.getContentText());
    Logger.log(`Fetched data from CurseForge for ID ${projectId}`);
    
    // Получаем список файлов модов
    const filesUrl = `https://api.curseforge.com/v1/mods/${projectId}/files`;
    const filesResponse = UrlFetchApp.fetch(filesUrl, { headers: headers });
    const filesData = JSON.parse(filesResponse.getContentText());

    // Сортируем файлы по дате создания и выбираем последний
    const sortedFiles = filesData.data.sort((a, b) => new Date(b.fileDate) - new Date(a.fileDate));
    let latestVersion = '';
    if (sortedFiles.length > 0) {
      latestVersion = sortedFiles[0].displayName || sortedFiles[0].fileName;
    }

    return {
      downloadCount: data.data.downloadCount || 0,
      latestVersion: latestVersion
    };
  } catch (error) {
    Logger.log(`Error fetching data for CurseForge project ID ${projectId}: ${error}`);
    return {
      downloadCount: 0,
      latestVersion: ''
    };
  }
}

function sortByColumns(sheet, popularityCol, nameCol) {
  const range = sheet.getRange(2, 1, sheet.getLastRow() - 1, sheet.getLastColumn());
  range.sort([
    { column: popularityCol, ascending: false }, // По популярности
    { column: nameCol, ascending: true }        // По имени мода
  ]);
}