Google Apps Script(GAS。Googleのサービス上で動かせるJavaScriptの実行環境)に大きなデータを同梱して、clasp push(手元のファイルをGASへ送るコマンド)を実行した。10分以上待たされたあと、返ってきたのは Internal error encountered. の1行だけだった。
原因はGASのプロジェクト全体の容量上限です。そして、この上限はバイト数ではなく文字数で数えないと当たりません。この記事は、私たちが社内で運用している業務ツールで実際にこの上限を踏んだときの記録と、それ以降「上限の手前で機械的に止める」ようにした運用の中身です。
先に結論を書きます(いずれも自社計測)。
- 39MB・15.7M文字は通り、32MB・21.5M文字は落ちた。 バイトで数えると大きい方が通っているので、バイトは上限の単位として説明がつかない
- 26MB・15.5M文字に縮めたら通った
- 以後は14.9M文字を予算にして、超えそうなら自動で削る。2026-08-11〜09-24の夜間反映43回はすべて成功、失敗0回
公式のクォータ表は、この問いに答えていない
GASの制限を調べると、上位に出てくるのは「1回の実行は6分まで」「トリガーは20個まで」「プロパティは500KBまで」といった同じ表です。2026-09-02 に私たちが検索上位10件を実際に開いて確認した範囲では(自社調査)、プロジェクト全体に何文字・何バイトまで置けるかを数字で書いたページは1件もありませんでした。
普段のGAS開発では、コードが数万文字を超えることはまずありません。だから誰も困らず、誰も書いていない。困るのは、GASのWebアプリに検索用のデータそのものを同梱するような使い方をしたときです。
私たちの場合は、数万件の業務データを一覧・全文検索できる社内ツールでした。データベースを別に立てず、HTMLファイルの中にデータを埋め込んでGASから配信する構成にしていました。サーバー代がかからず、Googleアカウントの権限管理にそのまま乗れるのが利点です。その代わり、データが増えるほどプロジェクトが膨らみます。
実測:バイトで考えると説明がつかない
2026-08-07 に、構成を変えながら3回 push した結果です(自社計測)。
| 構成 | 容量(バイト) | 文字数 | 結果 |
|---|---|---|---|
| データ本体+詳細データ8分割 | 約39MB | 約15.7M文字 | 成功 |
| データ本体+全文検索の索引 | 約32MB | 約21.5M文字 | Internal error encountered. |
| 索引を圧縮した版 | 約26MB | 約15.5M文字 | 成功 |
1行目と2行目を見比べてください。39MBが通って、それより小さい32MBが落ちています。 上限がバイトで決まっているなら、この並びは起こりません。
一方、文字数で並べると、15.7M文字は通り、21.5M文字は落ちています。バイトと文字数のどちらで数えるかと問われれば、矛盾しないのは文字数だけです。
なぜ同じくらいのデータで、バイトと文字数がこんなに食い違うのか。日本語はUTF-8(Webで標準的な文字の符号化方式)で1文字3バイト、英数字は1文字1バイトだからです。
- 詳細データは日本語の文章が中心 → 1文字あたりのバイト数が大きい → バイトは重いが文字数は少ない
- 全文検索の索引は英数字の記号列が中心 → 1文字あたり1バイト前後 → バイトは軽いが文字数は多い
本日(2026-09-24)、同じツールの現行ファイルを1本ずつ数え直しました(自社計測)。日本語の本文が中心のファイルは1文字あたり2.49〜2.51バイト、英数字の索引ファイルは1.00〜1.26バイトでした。プロジェクト全体では12.92M文字・23.01MB、平均1.78バイト/文字です。
つまり「前回39MBで通ったから、今回の32MBも通るはず」という判断は、中身の言語の比率が変わった瞬間に外れます。判断は必ず文字数で行う。これが最初の結論です。
失敗の出方が不親切なので、手順で守る
この上限でつまずくと、時間を大きく失います。理由は失敗の出方にあります。
- エラーメッセージが原因を言わない。 返ってくるのは
Internal error encountered.だけで、容量の話は一言も出ません。一時的な障害と見分けがつかないため、同じ push を何度もやり直すことになります - 落ちるまでに時間がかかる。 落ちた回は、送り始めてから10〜15分ほど待たされてから失敗しました(自社計測)。1回試すのに15分かかるので、二分探索で境界を探す気力が続きません
- 途中で別のエラーが混ざることがある。 長い push の途中で認証が切れて
Invalid Credentialsが出た回がありました。このとき、後続のデプロイ更新だけは成功してしまい、画面上は更新済みなのに中身は古いままという状態になりました
3つ目が一番危険です。対策として、夜間の自動反映では push の出力に「Pushed」の1行が含まれていなければ、その時点で止めてデプロイに進まないようにしました。終了コードだけでは信用しません。実行ログに残っている夜間反映43回(2026-08-11〜09-24)は、push とデプロイ更新がすべて成功し、所要時間は2.4〜4.2分・中央値3.35分でした(自社の実行ログ sync.log から集計)。
上限の手前で止める運用:予算14.9M文字と自動の削り
このツールのデータは毎日増えます。人が毎回文字数を数えるのは続きません。そこで、ビルド(配信用ファイルを組み立てる工程)の中に予算を持たせました。
- 予算は14.9M文字。 通った実績のある15.5M文字から、0.6M文字の余裕を取った値です
- 全文検索の索引以外のファイルを先に数え、残りの枠に索引が収まるまで、索引から語を削る
- 削るのは多くのデータに出てくる語から。出現件数が8,000件を超える語 → 6,000件 → 4,000件…と、9段階で基準を下げていきます。たくさんのデータに出てくる語は絞り込みの役に立たないので、削っても検索の実用性がいちばん落ちにくい
- 9段階すべて試しても収まらない場合は、「反映に失敗する可能性が高い」と警告を出す
もう1つ、別の安全装置もあります。開発中に索引を外へ出す別構成を試したとき、索引が無い状態の作業フォルダに対して素のビルドが走ると、索引込みで約19M文字になる見込みでした(自社計測の見積もり)。これは落ちる側の数字です。そこで、索引ファイルが無いのにデータ本体だけある状態を検知したら、push そのものを中止するようにしました。
それでも足りないときは、GASの外へ逃がす
予算の中で削っていくと、いずれ検索の質が落ちます。根本的には、大きなデータをGASプロジェクトの外に置くしかありません。私たちが効いた順に並べると、次の3つでした。
- 大きなデータはスプレッドシートへ逃がす。 全文検索の索引だけで6.8M文字、プロジェクト全体の46%を占めていました(2026-08-19 自社計測)。これをスプレッドシートに移すと、その分だけ本体のデータを増やせます。代わりに検索は0.6秒から数秒に遅くなりました
- 数値の並びを差分で持ち、36進数で縮める。 索引の中身は「この語が出てくるデータの番号」の並びです。番号そのものではなく前の番号との差を持ち、36進数(0-9とa-zの36文字で数を表す方法)の可変長で書くと、文字数が大きく減ります
- 本文を切り詰める。 1件あたりの文章の長さに上限を設けます
スプレッドシートに逃がすときにも別の上限があります。新しく作ったシートは既定で26列あるため、2列しか使わない索引でも行数が多いと、スプレッドシート全体のセル数上限(1,000万セル)に当たりました(2026-08-19 に発生)。使わない列を削除してから書き込むようにして解消しています。上限から逃げた先で、また別の上限を踏むということです。
分かっていないこと(正直に書く)
最後に、この記録の弱いところを書いておきます。
境界は15.7M文字と21.5M文字の間のどこか、としか言えません。 その間を刻んで試したことはありません。1回15分かかる失敗を繰り返す理由が無かったからです。
「15.7M文字は通った」という記録自体に、社内で食い違いがあります。 本日、関係するファイルを横断して確かめたところ、ビルドの設定と社内のメモは「15.7M文字で成功」、別のファイルのコメント(2026-08-19)は「15.7M文字で失敗、15.3M文字を安全線」と書いていました。どちらが正しいかを決める元の実行ログは残っていません。だから予算は、どちらの説でも安全側になる14.9M文字に置いています。
夜間の自動反映は、毎晩の文字数を記録に残していません。 ビルドの途中では文字数を画面に出していますが、実行ログ(sync.log)には「ビルド完了」と「デプロイ更新」しか残らない作りでした。そのため、この43回のうち上限にどこまで近づいた夜があったのかは、今からは分かりません。本日の実測は12.92M文字で、予算14.9M文字の86.7%です(自社計測)。
Googleがこの上限を文字数で数えていると確認したわけではありません。 言えるのは、「バイトでは説明がつかず、文字数なら矛盾しない」ところまでです。上限の値が将来変わる可能性もあります。
GASに大きなデータを同梱する設計を選ぶなら、次の3つを最初から入れておくことをおすすめします。
- 容量は文字数で数え、ビルドのたびに記録に残す
- 通った実績から余裕を取った予算を置き、超えそうなら機械的に削るか止める
- push の成否は終了コードではなく、成功を示す出力の1行で判定する