GASエラー解決ガイド|よくあるエラーTOP10と解決法
GAS(Google Apps Script)を使っていると、誰もが一度はエラーに悩まされます。
この記事では、GASでよく発生するエラーTOP10とその解決法を、具体的なコード例とともに解説します。エラーメッセージの読み方やデバッグのコツも紹介するので、自力でエラーを解決できるようになりましょう。
エラーメッセージの読み方
まず、エラーメッセージを正しく読み解く方法を覚えましょう。
エラーメッセージの構成
TypeError: Cannot read properties of undefined (reading 'getRange')
at processData (コード:15:23)
| 部分 | 意味 |
|---|---|
| TypeError | エラーの種類(型エラー) |
| Cannot read properties of undefined | 何が問題か(undefinedのプロパティを読もうとした) |
| (reading ‘getRange’) | どのプロパティか(getRange) |
| at processData | どの関数で発生したか |
| (コード:15:23) | 何行目の何文字目か |
エラーの種類
| エラー種類 | 意味 | よくある原因 |
|---|---|---|
| TypeError | 型に関するエラー | null/undefinedへのアクセス |
| ReferenceError | 参照エラー | 変数名のタイプミス |
| SyntaxError | 構文エラー | カッコの閉じ忘れ等 |
| RangeError | 範囲エラー | 配列の範囲外アクセス |
| Exception | GAS固有のエラー | API制限、権限不足等 |
よくあるエラーTOP10と解決法
1位: TypeError: Cannot read properties of undefined
最もよく見るエラーです。
エラー例
function myFunction() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('存在しないシート');
const value = sheet.getRange('A1').getValue(); // ここでエラー
}
原因
getSheetByName()で存在しないシート名を指定すると、nullが返されます。nullに対してgetRange()を呼ぼうとしてエラーになります。
解決法
function myFunction() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('シート1');
// nullチェックを追加
if (!sheet) {
console.error('シートが見つかりません');
return;
}
const value = sheet.getRange('A1').getValue();
}
2位: Exception: Service Spreadsheets failed while accessing document
エラー例
Exception: Service Spreadsheets failed while accessing document with id: xxxxx
原因
- スプレッドシートが削除された
- アクセス権限がない
- スプレッドシートIDが間違っている
解決法
function myFunction() {
try {
const ss = SpreadsheetApp.openById('スプレッドシートID');
// 処理
} catch (e) {
console.error('スプレッドシートにアクセスできません: ' + e.message);
// IDの確認、権限の確認を促す
}
}
確認ポイント:
- URLからIDをコピーし直す(
https://docs.google.com/spreadsheets/d/【ここがID】/edit) - スプレッドシートの共有設定を確認
- 実行アカウントに編集権限があるか確認
3位: Exception: You do not have permission to call…
エラー例
Exception: You do not have permission to call SpreadsheetApp.openById
原因
スクリプトに必要な権限が付与されていません。
解決法
- 初回実行時: 「承認が必要です」のダイアログで許可をクリック
- 権限の再設定: メニュー「編集」→「現在のプロジェクトのトリガー」→ 既存トリガーを削除 → 再作成
- マニフェストで明示的に指定:
// appsscript.json
{
"oauthScopes": [
"https://www.googleapis.com/auth/spreadsheets",
"https://www.googleapis.com/auth/gmail.send"
]
}
4位: Exception: Exceeded maximum execution time
エラー例
Exception: Exceeded maximum execution time
原因
GASの実行時間制限(6分)を超えました。
解決法
方法1: 処理を分割する
function processBatch() {
const sheet = SpreadsheetApp.getActiveSheet();
const lastRow = sheet.getLastRow();
// プロパティに進捗を保存
const props = PropertiesService.getScriptProperties();
let startRow = parseInt(props.getProperty('startRow')) || 2;
const batchSize = 100; // 1回で処理する行数
const endRow = Math.min(startRow + batchSize - 1, lastRow);
for (let row = startRow; row <= endRow; row++) {
// 処理
}
if (endRow < lastRow) {
// 次のバッチのために開始行を保存
props.setProperty('startRow', (endRow + 1).toString());
// 1分後に再実行するトリガーを設定
ScriptApp.newTrigger('processBatch')
.timeBased()
.after(60000)
.create();
} else {
props.deleteProperty('startRow');
}
}
方法2: 不要な処理を削減
// NG: ループ内で毎回getRange
for (let i = 1; i <= 1000; i++) {
sheet.getRange(i, 1).setValue(i); // 遅い
}
// OK: 配列でまとめて書き込み
const data = [];
for (let i = 1; i <= 1000; i++) {
data.push([i]);
}
sheet.getRange(1, 1, 1000, 1).setValues(data); // 速い
5位: ReferenceError: xxx is not defined
エラー例
ReferenceError: sheetName is not defined
原因
変数が定義されていない、またはスコープ外で参照しています。
解決法
// NG: タイプミス
const sheetname = 'シート1';
console.log(sheetName); // 大文字小文字が違う
// OK: 正しい変数名
const sheetName = 'シート1';
console.log(sheetName);
よくあるパターン:
- 大文字小文字の間違い(
sheetNamevssheetname) - 変数宣言の忘れ(
const/letがない) - 関数外で定義した変数を関数内で参照(スコープ問題)
6位: SyntaxError: Unexpected token
エラー例
SyntaxError: Unexpected token ')'
原因
構文エラー。カッコや引用符の対応が間違っています。
解決法
チェックポイント:
(){}[]の対応'"の閉じ忘れ- カンマ
,の過不足 - セミコロン
;の位置
// NG: カッコが閉じていない
if (value > 0 {
console.log('positive');
}
// OK
if (value > 0) {
console.log('positive');
}
Tips: スクリプトエディタで Ctrl+Shift+F(フォーマット)を実行すると、構文エラーの箇所が分かりやすくなります。
7位: Exception: Rate Limit Exceeded
エラー例
Exception: Rate Limit Exceeded
原因
短時間にAPIを呼びすぎて、レート制限に達しました。
解決法
function processWithDelay() {
const items = getItems();
for (let i = 0; i < items.length; i++) {
callExternalAPI(items[i]);
// リクエスト間に待機を入れる
Utilities.sleep(1000); // 1秒待機
}
}
外部API別の対策:
| API | 制限 | 対策 |
|---|---|---|
| OpenAI | 60 RPM(無料) | 1秒以上の間隔 |
| Gmail送信 | 100件/日(無料) | 日をまたいで送信 |
| UrlFetchApp | 20,000回/日 | バッチ処理で回数削減 |
8位: TypeError: Cannot convert undefined or null to object
エラー例
TypeError: Cannot convert undefined or null to object
原因
Object.keys()やObject.values()にnull/undefinedを渡しています。
解決法
// NG
const obj = null;
Object.keys(obj); // エラー
// OK: デフォルト値を設定
const obj = null;
Object.keys(obj || {}); // 空のオブジェクトとして処理
9位: Exception: Invalid argument: range
エラー例
Exception: Invalid argument: range
原因
getRange()に無効な引数を渡しています。
解決法
// NG: 0行目は存在しない(GASは1始まり)
sheet.getRange(0, 1);
// NG: 負の値
sheet.getRange(-1, 1);
// NG: 範囲外
sheet.getRange(1, 100); // 100列目が存在しない場合
// OK
sheet.getRange(1, 1); // A1セル
sheet.getRange('A1:B10'); // A1:B10範囲
ポイント: GASの行・列番号は 1始まり です(0始まりではない)。
10位: Exception: Invalid email address
エラー例
Exception: Invalid email address: undefined
原因
GmailApp.sendEmail()に無効なメールアドレスを渡しています。
解決法
function sendEmail() {
const email = sheet.getRange('A1').getValue();
// メールアドレスの検証
if (!email || !isValidEmail(email)) {
console.error('無効なメールアドレス: ' + email);
return;
}
GmailApp.sendEmail(email, '件名', '本文');
}
function isValidEmail(email) {
const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return regex.test(email);
}
番外編:知っておくと便利なエラー3選
TOP10に加えて、実務でよく遭遇するエラーを紹介します。
番外1: Exception: Document is missing
エラー例
Exception: Document is missing (perhaps it was deleted, or you don't have read access?)
原因
参照先のGoogleドキュメント/スプレッドシートが削除された、またはゴミ箱に移動された状態です。
解決法
function safeOpenDocument(docId) {
try {
const doc = DocumentApp.openById(docId);
return doc;
} catch (e) {
if (e.message.includes('Document is missing')) {
console.error('ドキュメントが見つかりません。削除されたか、ゴミ箱にある可能性があります。');
// 管理者に通知する処理を追加
notifyAdmin('ドキュメント消失: ' + docId);
}
return null;
}
}
番外2: Exception: Quota exceeded
エラー例
Exception: Quota exceeded: Email Recipients per day
原因
GASの日次クォータ(利用制限)に達しました。
解決法
クォータ一覧(無料アカウント):
| サービス | 日次制限 |
|---|---|
| メール送信 | 100件/日 |
| UrlFetchApp | 20,000回/日 |
| スプレッドシート作成 | 250件/日 |
| トリガー実行 | 90分/日(合計) |
// 送信前にクォータを確認
function checkEmailQuota() {
const remaining = MailApp.getRemainingDailyQuota();
console.log('残りメール送信可能数: ' + remaining);
if (remaining < 10) {
console.warn('クォータ残りわずか!処理を中断します');
return false;
}
return true;
}
番外3: TypeError: xxx.getValues is not a function
エラー例
TypeError: sheet.getValues is not a function
原因
RangeオブジェクトとSheetオブジェクトを混同しています。getValues()はRangeのメソッドです。
解決法
// NG: sheetに直接getValues()は使えない
const sheet = SpreadsheetApp.getActiveSheet();
const data = sheet.getValues(); // エラー!
// OK: まずgetDataRange()でRangeを取得
const sheet = SpreadsheetApp.getActiveSheet();
const data = sheet.getDataRange().getValues(); // 正しい
覚え方: Sheet → Range → Values の順番でメソッドを呼ぶ
デバッグのコツ
1. console.log / Logger.log を活用
function debugExample() {
const sheet = SpreadsheetApp.getActiveSheet();
console.log('シート名: ' + sheet.getName()); // 確認用
const data = sheet.getDataRange().getValues();
console.log('データ行数: ' + data.length); // 確認用
console.log('1行目: ' + JSON.stringify(data[0])); // 配列の中身を確認
for (let i = 0; i < data.length; i++) {
console.log(`処理中: ${i + 1}行目`); // 進捗確認
// 処理
}
}
実行ログの確認方法:
- スクリプトエディタ下部の「実行ログ」パネル
- メニュー「表示」→「ログ」
2. try-catch でエラーをキャッチ
function safeProcess() {
try {
// エラーが起きる可能性のある処理
const result = riskyOperation();
return result;
} catch (error) {
// エラー情報を詳しく記録
console.error('エラー発生: ' + error.message);
console.error('スタックトレース: ' + error.stack);
// 必要に応じてメール通知
sendErrorNotification(error);
return null;
}
}
3. 段階的に実行
大きな処理は小さく分割してテスト:
// ステップ1: データ取得のみテスト
function step1_getData() {
const data = fetchData();
console.log(data);
}
// ステップ2: データ加工のみテスト
function step2_processData() {
const testData = [['テスト', 100]];
const result = processData(testData);
console.log(result);
}
// ステップ3: 書き込みのみテスト
function step3_writeData() {
const testResult = 'テスト結果';
writeToSheet(testResult);
}
4. ブレークポイントとデバッガーの使い方
GASエディタにはデバッガー機能があります。
使い方:
- 行番号の左側をクリック → 赤い点(ブレークポイント)が表示
- 「デバッグ」ボタン(虫のアイコン)をクリック
- ブレークポイントで実行が一時停止
- 右側のパネルで変数の中身を確認
- 「ステップイン」ステップオーバーで1行ずつ実行
確認できること:
- 変数の現在値
- オブジェクトの中身(展開して確認可能)
- 関数の呼び出し履歴(コールスタック)
5. エラーハンドリングのテンプレート
本番運用で使える堅牢なテンプレート:
/**
* エラーハンドリング付きメイン処理
*/
function mainWithErrorHandling() {
const startTime = new Date();
let processedCount = 0;
try {
// 前処理
console.log('処理開始: ' + startTime.toLocaleString());
// メイン処理
processedCount = doMainProcess();
// 正常終了
console.log(`処理完了: ${processedCount}件処理しました`);
} catch (error) {
// エラー発生時の処理
const errorInfo = {
message: error.message,
stack: error.stack,
timestamp: new Date().toLocaleString(),
processedCount: processedCount
};
console.error('エラー詳細:', JSON.stringify(errorInfo, null, 2));
// エラー通知(メールやSlack)
sendErrorAlert(errorInfo);
} finally {
// 必ず実行される後処理
const endTime = new Date();
const duration = (endTime - startTime) / 1000;
console.log(`実行時間: ${duration}秒`);
}
}
/**
* エラー通知
*/
function sendErrorAlert(errorInfo) {
const recipient = 'your-email@example.com';
const subject = '【GASエラー通知】処理でエラーが発生しました';
const body = `
エラーが発生しました。
■ エラーメッセージ
${errorInfo.message}
■ 発生日時
${errorInfo.timestamp}
■ 処理済み件数
${errorInfo.processedCount}件
■ スタックトレース
${errorInfo.stack}
`;
MailApp.sendEmail(recipient, subject, body);
}
トラブルシューティングフローチャート
エラーが発生した!
│
▼
┌────────────────┐
│ エラーメッセージを│
│ 確認する │
└───────┬────────┘
│
▼
┌────────────────┐ YES ┌────────────────┐
│ TypeError? │─────────→│ null/undefined │
│ │ │ をチェック │
└───────┬────────┘ └────────────────┘
│ NO
▼
┌────────────────┐ YES ┌────────────────┐
│ Exception? │─────────→│ 権限・制限を │
│ │ │ 確認 │
└───────┬────────┘ └────────────────┘
│ NO
▼
┌────────────────┐ YES ┌────────────────┐
│ SyntaxError? │─────────→│ カッコ・引用符 │
│ │ │ を確認 │
└───────┬────────┘ └────────────────┘
│ NO
▼
┌────────────────┐
│ console.logで │
│ 変数の中身確認 │
└────────────────┘
まとめ
エラー解決の3ステップ
- エラーメッセージを読む(種類・行番号を確認)
- 原因を特定する(変数の中身をconsole.logで確認)
- 修正してテスト(小さく分割して検証)
よくあるエラーまとめ
| エラー | 主な原因 | 対策 |
|---|---|---|
| Cannot read properties of undefined | null/undefinedへのアクセス | nullチェック追加 |
| Service failed | アクセス権限なし | 権限・ID確認 |
| Exceeded maximum execution time | 6分超過 | 処理分割 |
| Rate Limit Exceeded | API呼びすぎ | 待機時間追加 |
次のステップ
- GAS×ChatGPT入門|基本的な連携方法[リンク予定]
- GAS×ChatGPTで一括処理[リンク予定]
- GAS公式ドキュメント
エラーは成長のチャンス。この記事を参考に、自力でエラーを解決できるスキルを身につけましょう!
この記事は SkillUp Labs が執筆しました。質問があればお気軽にお問い合わせください。
コメント