GAS『Cannot Call Method on Null』の原因と対処法
- 作成日 2025.10.14
- その他
Google Apps Scriptで「Cannot call method ‘xxx’ of null」や「Cannot read properties of null (reading ‘xxx’)」は、nullに対してメソッド呼び出しを行ったときに出る。どの値がnullなのかを特定し、取得処理・権限・データの前提を直すのが近道。
目次
- 1. エラーの意味と代表メッセージ
- 2. 発生条件の早見表
- 3. まず特定:どの変数がnullかをログで洗い出す
- 4. 最頻出1:getSheetByName が null(シート名違い・末尾空白・誤プロジェクト)
- 5. 最頻出2:ファイル/ID/権限の問題(Drive/Docs/Slides)
- 6. 最頻出3:イベント引数 e が無い(手動実行)
- 7. 最頻出4:Properties/Cache が null(文字列メソッド呼び出し)
- 8. 最頻出5:外部APIのJSONが期待通りでない(null安全にアクセス)
- 9. 最頻出6:範囲/値の取り扱い(空とnullの違い)
- 10. ユーティリティ:nullを早期検知して意味のあるエラーに置換
- 11. NG→OKスニペット集
- 12. 再現→修正の通し例(シート名ミス)
- 13. チェックリスト(上から順に)
エラーの意味と代表メッセージ
TypeError: Cannot call method 'getRange' of null
TypeError: Cannot read properties of null (reading 'appendRow')
TypeError: Cannot call method 'getBody' of null・対象がnullのまま .getRange() や .appendRow() などを呼んでいる。
発生条件の早見表
□ getSheetByName が null を返したのに .getRange() を呼んだ
□ openById / DriveApp.getFileById が対象を見つけられない(ID違い/権限なし/ごみ箱)
□ onEdit/onOpen/doGet/doPost の e が未定義/null(手動実行など)
□ PropertiesService/CacheService から null を受け取り .trim() などを呼んだ
□ 外部APIのJSONで想定キーが null/欠落
□ 正規表現/配列/オブジェクトの操作対象が実は nullまず特定:どの変数がnullかをログで洗い出す
function trace(v, name) {
console.log(name, {isNull: v === null, isUndef: v === undefined, type: typeof v, value: v});
}
function demo() {
const ss = SpreadsheetApp.openById('YOUR_SHEET_ID');
const sh = ss.getSheetByName('Data');
trace(sh, 'sheet'); // ← nullならここで判明
sh.getRange('A1').setValue('ok');
}・例外直前の値を必ず記録してから修正に着手。
最頻出1:getSheetByName が null(シート名違い・末尾空白・誤プロジェクト)
// NG
const sh = SpreadsheetApp.openById(ID).getSheetByName('Data '); // 末尾空白
sh.getRange('A1').setValue('x'); // Cannot call method 'getRange' of null
// OK:安全取得
function getSheetSafe(id, name) {
const ss = SpreadsheetApp.openById(id);
const sh = ss.getSheetByName(name);
if (!sh) throw new Error(`シートが見つかりません: "${name}"`);
return sh;
}
const sh2 = getSheetSafe(ID, 'Data');・openByIdにURL全体を渡すミスにも注意(IDのみ渡す)。
最頻出2:ファイル/ID/権限の問題(Drive/Docs/Slides)
// NG:別アカウント所有/ごみ箱/共有ドライブ権限なし
const file = DriveApp.getFileById(FILE_ID); // ここで例外 or null相当の扱いに
const doc = DocumentApp.openById(DOC_ID); // docがnull → getBodyで落ちる
// OK:存在と状態を確認(権限が無ければ先に共有)
function assertFile(id) {
const f = DriveApp.getFileById(id);
console.log({name: f.getName(), trashed: f.isTrashed()});
return f;
}・共同編集権がない/ごみ箱入り/共有ドライブのアクセス設定で失敗しやすい。
最頻出3:イベント引数 e が無い(手動実行)
// NG:手動実行で e が undefined → e.range 参照で落ちる
function onEdit(e) {
const a1 = e.range.getA1Notation(); // TypeError
}
// OK:ガード
function onEdit(e) {
if (!e || !e.range) return; // 直接実行時は何もしない
const a1 = e.range.getA1Notation();
}・doPost/doGetも同様に e?.postData?.contents を必ず確認。
最頻出4:Properties/Cache が null(文字列メソッド呼び出し)
// NG
const token = PropertiesService.getScriptProperties().getProperty('API_TOKEN');
const trimmed = token.trim(); // tokenがnull → TypeError
// OK
const token2 = (PropertiesService.getScriptProperties().getProperty('API_TOKEN') || '').trim();
if (!token2) throw new Error('API_TOKEN が未設定');・getPropertyは未設定ならnullを返す。デフォルト値か検証を挟む。
最頻出5:外部APIのJSONが期待通りでない(null安全にアクセス)
// NG
const res = UrlFetchApp.fetch(url);
const json = JSON.parse(res.getContentText());
const name = json.data.user.name.toUpperCase(); // dataやuserがnullで落ちる
// OK(オプショナルチェーン/デフォルト)
const name2 = json?.data?.user?.name;
const upper = (typeof name2 === 'string') ? name2.toUpperCase() : 'UNKNOWN';
・失敗時レスポンスや仕様変更でキーが消えることがある。
最頻出6:範囲/値の取り扱い(空とnullの違い)
// getValues() の空セルは ''(空文字)で返るのが通常
const values = sh.getRange(2,1,10,2).getValues();
values.forEach(r => {
const v = r[0];
// v === '' なら空セル、v === null のパターンは別API由来で稀
});・「空」=”と「null」を混同しない。nullチェックは厳密に。
ユーティリティ:nullを早期検知して意味のあるエラーに置換
const U = {
req(v, msg='必須値がnull/undefinedです') { if (v == null) throw new Error(msg); return v; },
getSheet(id, name) {
const ss = SpreadsheetApp.openById(id);
const sh = ss.getSheetByName(name);
return this.req(sh, `シートが見つかりません: "${name}"`);
},
str(v, def='') { return v == null ? def : String(v); }
};
// 使用例
const sh = U.getSheet(ID, 'Data');
const token = U.str(PropertiesService.getScriptProperties().getProperty('TOKEN'));
・「どこでnullだったか」を明確にし、原因追跡を容易にする。
NG→OKスニペット集
// NG:URLをopenByIdに渡す
SpreadsheetApp.openById('https://docs.google.com/spreadsheets/...');
// OK:IDのみ
SpreadsheetApp.openById('1AbCdEfGhIjK...');
// NG:存在未確認でメソッド呼び出し
const sh = ss.getSheetByName('Data');
sh.appendRow(['a']); // 失敗時にnullで落ちる
// OK:確認してから
const sh2 = ss.getSheetByName('Data');
if (!sh2) throw new Error('Data シートなし');
sh2.appendRow(['a']);
// NG:e未確認
function doPost(e){ const body = e.postData.contents; /* ... */ }
// OK
function doPost(e){
const body = e?.postData?.contents;
if (!body) return ContentService.createTextOutput('empty');
// ...
}再現→修正の通し例(シート名ミス)
// 再現(落ちる)
function failCase() {
const ss = SpreadsheetApp.openById('YOUR_SHEET_ID');
const sh = ss.getSheetByName('Data '); // スペース付き
sh.getRange('A1').setValue('x'); // Cannot call method 'getRange' of null
}
// 修正(安全取得)
function fixed() {
const ss = SpreadsheetApp.openById('YOUR_SHEET_ID');
const name = 'Data';
const sh = ss.getSheetByName(name);
if (!sh) throw new Error(`シート "${name}" が見つかりません`);
sh.getRange('A1').setValue('ok');
}チェックリスト(上から順に)
□ 例外直前の変数をログして、nullの正体を特定したか
□ シート名/ID/URLの渡し方は正しいか(IDのみ・末尾空白なし)
□ 対象ファイルに編集権限があり、ごみ箱/共有ドライブ設定も問題ないか
□ イベント引数 e の存在を確認し、手動実行時は安全に抜けるか
□ Properties/Cache のnullをデフォルト値や検証で吸収しているか
□ 外部JSONには ?. と型確認でアクセスしているか
□ 「空文字」と「null」を区別して扱っているか-
前の記事
GAS『Script Function Not Found』の原因と対処法 2025.10.10
-
次の記事
GAS『Service Timeout』の原因と対処法 2025.10.15
コメントを書く