MENU

GASエラー解決ガイド|よくあるエラーTOP10と解決法

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);

よくあるパターン:

  • 大文字小文字の間違い(sheetName vs sheetname
  • 変数宣言の忘れ(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();  // 正しい

覚え方: SheetRangeValues の順番でメソッドを呼ぶ


デバッグのコツ

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呼びすぎ 待機時間追加

次のステップ

エラーは成長のチャンス。この記事を参考に、自力でエラーを解決できるスキルを身につけましょう!


この記事は SkillUp Labs が執筆しました。質問があればお気軽にお問い合わせください。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

コメント

コメントする

目次