GAS『Invalid Argument: Expected』の原因と対処法

GAS『Invalid Argument: Expected』の原因と対処法

Apps Scriptが受け取った引数の型・形式・個数がメソッドの期待と違うと発生する。A1表記と数値の取り違え、2次元配列のサイズ不一致、Date型やURL文字列の誤り、sendEmailのオーバーロード間違い、fetchのオプション型不整合などが典型。よくある発生条件を整理し、すぐに直せる修正パターンをまとめた。

エラーの意味と代表メッセージ

「Invalid argument: Expected …」や「Invalid argument: url」「Invalid argument: id」など、呼び出し先が“この位置には〇〇型/形式の引数が必要”と判断したときに出る。多くは型の取り違えか、値のラップ/展開方法のミス。

発生条件の早見表

・getRangeにA1表記を渡すべき所で数値(または逆)

・setValuesに1次元配列やサイズ不一致の2次元配列を渡した

・Utilities.formatDateやシートの日時演算にDateではなく文字列を渡した

・UrlFetchApp.fetchの第2引数に不正なオプション(文字列/配列)を渡した

・MailApp.sendEmailのオーバーロードを取り違え、型が合っていない

・JSON.parseにオブジェクトを渡している(文字列でない)

・CacheService.putの有効期限が範囲外(1〜600秒)

・Trigger作成APIに不正な関数名/対象/間隔を渡した

・Advanced Services(Sheets/Drive等)に仕様外のボディを渡した

ケース1:getRangeの指定ミス(A1表記 vs 行列指定)

// NG:行・列指定のつもりでA1文字列を渡している
const r = sheet.getRange('2', '3'); // Invalid argument
// OK:どちらかに統一
sheet.getRange('B2');                // A1表記
sheet.getRange(2, 2);                // 行・列(1始まり)

ケース2:setValuesは“2次元配列+サイズ一致”が必須

// NG:1次元配列
sheet.getRange(1,1,3,1).setValues(['a','b','c']); // Invalid argument
// OK:2次元に
sheet.getRange(1,1,3,1).setValues([['a'],['b'],['c']]);

// NG:サイズ不一致(範囲3x2に2x2)
sheet.getRange(1,1,3,2).setValues([['a','b'],['c','d']]); // Invalid argument
// OK:範囲と同じ3x2で渡す
sheet.getRange(1,1,3,2).setValues([['a','b'],['c','d'],['e','f']]);

ケース3:Dateを期待する場所に文字列を渡している

// NG:formatDateの第1引数はDate型
Utilities.formatDate("2025-10-20", "Asia/Tokyo", "yyyy-MM-dd"); // Invalid argument
// OK
const d = new Date("2025-10-20T00:00:00+09:00");
Utilities.formatDate(d, "Asia/Tokyo", "yyyy-MM-dd");

ケース4:UrlFetchApp.fetch / fetchAll のオプション型不整合

// NG:第2引数に文字列
UrlFetchApp.fetch('https://example.com', 'GET'); // Invalid argument
// OK:オプションはオブジェクト
UrlFetchApp.fetch('https://example.com', { method: 'get', muteHttpExceptions: true });

// NG:fetchAllは「リクエストオブジェクト配列」
UrlFetchApp.fetchAll(['https://a','https://b']); // Invalid argument
// OK
UrlFetchApp.fetchAll([{url:'https://a'},{url:'https://b'}]);

ケース5:MailApp.sendEmailのオーバーロード取り違え

// 代表的OKパターン(シンプル版)
MailApp.sendEmail('user@example.com', '件名', '本文');

// オプション版(オブジェクトで渡す)
MailApp.sendEmail({
  to: 'user@example.com',
  subject: '件名',
  htmlBody: '<b>本文</b>',
  cc: 'cc@example.com'
});

// NG:件名にオブジェクト、本文に数値など
MailApp.sendEmail('user@example.com', {sub:'件名'}, 123); // Invalid argument

ケース6:JSON.parse/JSON.stringifyの引数型が不正

// NG:parseは“文字列”を期待
const obj = {a:1};
JSON.parse(obj); // Invalid argument
// OK
JSON.parse('{"a":1}');

// NG:stringifyはオブジェクト/配列を期待(循環参照に注意)
const circular = {}; circular.me = circular;
JSON.stringify(circular); // これは別の例外(循環参照)

ケース7:CacheService.putの秒数範囲、キー/値の型

// NG:期限が600秒超
CacheService.getScriptCache().put('k', 'v', 1200); // Invalid argument
// OK:1〜600秒
CacheService.getScriptCache().put('k', 'v', 300);

// NG:キー/値にオブジェクト
CacheService.getScriptCache().put('k', {a:1}, 60); // Invalid argument
// OK:文字列化
CacheService.getScriptCache().put('k', JSON.stringify({a:1}), 60);

ケース8:Trigger作成APIの引数(関数名・対象・間隔)

// NG:存在しない関数名
ScriptApp.newTrigger('notExists').timeBased().everyMinutes(5).create(); // Invalid argument
// OK:実在する関数を指定
function job(){ /*...*/ }
ScriptApp.newTrigger('job').timeBased().everyMinutes(5).create();

// NG:スプレッドシート対象を未指定のままonEdit
ScriptApp.newTrigger('job').onEdit().create(); // Invalid argument
// OK:対象を明示
ScriptApp.newTrigger('job').forSpreadsheet(SpreadsheetApp.getActive()).onEdit().create();

ケース9:Advanced Sheets/Drive APIのボディ構造が仕様外

// NG:Values.updateのbodyは {values: 2次元配列}
Sheets.Spreadsheets.Values.update({ value: 'x' }, SHEET_ID, 'A1',
  { valueInputOption: 'RAW' }); // Invalid argument
// OK
Sheets.Spreadsheets.Values.update({ values: [['x']] }, SHEET_ID, 'A1',
  { valueInputOption: 'RAW' });

ケース10:配列/オブジェクトAPIでのコールバック型ミス

// NG:Array.mapに関数以外
[1,2,3].map('x'); // Invalid argument
// OK
[1,2,3].map(n => n*2);

入力検証のテンプレ(事前に“期待どおりか”を保証)

const V = {
  is2D: (a) => Array.isArray(a) && a.every(r => Array.isArray(r)),
  req: (cond, msg) => { if (!cond) throw new Error(msg); }
};

function safeSetValues(range, values) {
  V.req(V.is2D(values), '2次元配列が必要です');
  V.req(values.length > 0 && values[0].length > 0, '空配列は不可');
  const r = range.getNumRows(), c = range.getNumColumns();
  V.req(values.length === r && values[0].length === c, '範囲とサイズが一致しません');
  range.setValues(values);
}

診断のコツ(どの引数が不正かを素早く突き止める)

・例外行の直前でtypeof/Array.isArray/値のログを出す

・A1表記か数値指定かを呼び出しごとに統一する

・fetch/sendEmailは“どのオーバーロードを使うか”を明確にする

・Advanced Servicesは公式のサンプルに沿って最小ボディで通す→徐々に拡張

チェックリスト(上から順に潰す)

・引数の型は期待と一致しているか(string/number/boolean/Date/object/2次元配列)

・A1表記と行列指定を混ぜていないか

・setValuesは2次元+サイズ一致か

・fetch/sendEmailは正しいシグネチャを選んでいるか

・JSON.parseに“文字列”を渡しているか

・CacheServiceの期限は1〜600秒か、値は文字列か

・Trigger作成時に実在の関数名と適切なターゲットを指定しているか

・Advanced Servicesのリクエストボディは公式の型に沿っているか