GASで「Exceeded maximum execution time」エラーが発生する原因と解決策
最終更新日: 2026-08-27
30秒でわかる原因と解決策
原因: Google Apps Script(GAS)には1回あたりの最大実行時間制限(通常アカウントは6分、有料Workspaceアカウントは30分)が設定されており、大量のデータをループ処理などで一気に処理しようとすると、この制限時間を超えてしまいエラーが発生します。 解決策: 処理を小さな単位に分割(バッチ処理)し、
PropertiesServiceなどを使って「どこまで処理したか」を保存・記憶させます。その後、時間主導型トリガーをプログラムから動的に設定して、処理を自動で継続させましょう。
修正コード(Before / After)
❌ エラーが発生するコード
// 大量の行を一気に処理しようとして6分の制限に引っかかる例
function processAllRows() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var rows = sheet.getDataRange().getValues();
// データの行数が数千行以上ある場合、ここでタイムアウトしやすい
for (var i = 1; i < rows.length; i++) {
// 重い処理(外部API呼び出しや複雑な計算など)
Logger.log("Processing row: " + i);
// 例: 重い外部API連携
UrlFetchApp.fetch("https://api.example.com/data?id=" + rows[i][0]);
}
}
⭕ 修正後の推奨コード
// 制限時間内に終わるよう処理を分割し、トリガーで継続する例
function processInBatches() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var rows = sheet.getDataRange().getValues();
var props = PropertiesService.getScriptProperties();
// 前回の続きのインデックスを取得(初期値は1行目のデータ)
var startIndex = parseInt(props.getProperty('LAST_INDEX') || '1', 10);
var batchSize = 50; // 1回あたりの処理件数
var startTime = new Date().getTime();
var timeLimit = 4 * 60 * 1000; // 安全のため4分で打ち切る
for (var i = startIndex; i < rows.length; i++) {
// 制限時間が近づいたら中断
if (new Date().getTime() - startTime > timeLimit) {
props.setProperty('LAST_INDEX', i.toString());
setupContinuationTrigger();
Logger.log("タイムアウト防止のため中断します。次回インデックス: " + i);
return;
}
// 重い処理の実行
UrlFetchApp.fetch("https://api.example.com/data?id=" + rows[i][0]);
}
// すべて完了したらプロパティをクリア
props.deleteProperty('LAST_INDEX');
Logger.log("すべての処理が完了しました。");
}
// 継続用のトリガーを設定するヘルパー関数
function setupContinuationTrigger() {
// 既存の同名トリガーが重複しないように削除
var triggers = ScriptApp.getProjectTriggers();
triggers.forEach(function(trigger) {
if (trigger.getHandlerFunction() === 'processInBatches') {
ScriptApp.deleteTrigger(trigger);
}
});
// 1分後に再実行するトリガーを作成
ScriptApp.newTrigger('processInBatches')
.timeBased()
.after(1 * 60 * 1000)
.create();
}
よくある発生パターンと解説
Exceeded maximum execution time は、Google Apps Scriptの開発において非常に頻繁に遭遇するエラーの一つです。主に以下のパターンで発生します。
- スプレッドシートの行数が多すぎる
数千〜数万行あるデータを
forやwhileループで1行ずつ処理している場合。 - 外部APIへのリクエストを大量に繰り返している
UrlFetchApp.fetch()はネットワーク遅延を伴うため、ループ内で何回も呼び出すとすぐに数分が経過してしまいます。 - 無駄なセル読み書き(Read/Write)が多い
ループの中で
getActiveSheet().getRange().setValue()などを毎回実行していると、GASの実行速度が著しく低下します。一括取得(getValues)と一括書き込み(setValues)を使用することが基本ですが、それでもデータ量が多すぎる場合は上記のバッチ処理が必要です。
よくある質問 (FAQ)
Q1: 無料アカウントと有料アカウント(Google Workspace)で制限時間は違いますか?
A: はい、異なります。無料のGoogleアカウント(@gmail.com)では1回の実行あたり最大6分ですが、Google Workspace(有料版)のアカウントでは最大30分まで拡張されます。ただし、30分であっても大量データの場合はタイムアウトするリスクがあるため、バッチ処理の実装を推奨します。
Q2: 途中で中断した処理の「続き」から再開するにはどうすればよいですか?
A: 上記の修正コードのように PropertiesService を使用して現在の進捗(インデックスやID)をスクリプトプロパティに保存しておき、次回実行時にその値から読み込みを再開するのが一般的です。
Q3: トリガーが無限ループしてしまわないか心配です。
A: 処理がすべて完了した時点で props.deleteProperty('LAST_INDEX') を呼び出し、トリガーを削除(または完了判定を入れて新規トリガーを作成しないように)するロジックを必ず組み込んでください。これにより無限ループを防ぐことができます。