How to Deal with “Exceeded maximum execution time” in Google Apps Script

* If you need help with the content of this article for work or development, individual support is available.

When you are running Google Apps Script against a spreadsheet, Gmail, or Drive and you see

Exceeded maximum execution time

it usually means that your script has hit the maximum allowed execution time for a single run. The script itself may be logically correct, but Apps Script forcibly stops it once it runs too long. This section explains what that limit means and how to design scripts that avoid hitting it.

What the Error Actually Means

Apps Script enforces strict limits on how long a single execution can run. Typical values are:

  • Manual runs, simple triggers, time-based triggers: roughly 6 minutes per execution
  • Web apps or custom functions are also subject to a hard upper bound in the range of several minutes

In other words, even a valid script will be terminated if it keeps running beyond the limit. The real solution is therefore not to extend the limit, but to redesign your script so that each run finishes within a few minutes.

Typical Patterns That Cause Timeouts

You are likely to see this error in scenarios like:

  • Processing thousands of rows in a spreadsheet with a for loop that calls getValue() / setValue() per row
  • Scanning a large number of Gmail messages and updating labels one by one
  • Iterating over many Drive files and copying or moving each file separately
  • Making hundreds of requests to an external API in a single run

All these patterns share two characteristics: frequent I/O with Google services and long-running loops. To avoid timeouts, you need to batch operations and split processing into smaller units.

Core Strategies: Reduce, Speed Up, Split

You can think about timeout mitigation using three main strategies:

  1. Reduce the amount of work
    • Limit processing to only the rows, columns, messages, or files that are truly required
    • Skip irrelevant items as early as possible in your loops
  2. Speed up each unit of work (batch operations)
    • Use getValues() / setValues() to read and write spreadsheet data in bulk
    • Avoid repeated calls to SpreadsheetApp, GmailApp, DriveApp, etc., inside tight loops
  3. Split the job into multiple runs
    • Do not attempt to finish everything in one execution
    • Process 100–200 items per run and store progress so that the next execution can continue where the previous one left off

Practical Pattern #1: Batch Processing with Progress Tracking

Here is a typical pattern for processing a spreadsheet in batches of 100 rows, while remembering the current position with PropertiesService.

functionprocessBatch() {<br>constsheet = SpreadsheetApp.getActiveSheet();<br>constprops = PropertiesService.getScriptProperties();<br>conststartRow = Number(props.getProperty('CURRENT_ROW') || 2);<br>constbatchSize = 100;<br>constlastRow = sheet.getLastRow();<br>if (startRow > lastRow) {<br>props.deleteProperty('CURRENT_ROW');<br>Logger.log('All rows processed.');<br>return;<br>}<br>constendRow = Math.min(startRow + batchSize - 1, lastRow);<br>constrange = sheet.getRange(startRow, 1, endRow - startRow + 1, 5);<br>constvalues = range.getValues();<br>for (leti = 0; i < values.length; i++) {<br>constrow = values[i];<br>// Perform your processing here and update row elements<br>}<br>range.setValues(values);<br>props.setProperty('CURRENT_ROW', String(endRow + 1));<br>Logger.log(`Processed rows ${startRow} to ${endRow}.`);<br>}

Combined with a time-based trigger (e.g., every 5 minutes), this pattern allows you to complete large jobs without ever hitting the execution time limit.

Practical Pattern #2: Using Triggers for “Chunked” Execution

Batch processing works particularly well with time-based triggers:

  • Set up a trigger that calls processBatch() every few minutes
  • Each run processes only a small subset of the data
  • Progress is stored using PropertiesService so that each run resumes from the previous point

This design allows your script to keep working in the background instead of trying to handle everything in one long execution.

Practical Pattern #3: Move I/O Out of Loops

I/O operations inside loops are a common performance killer. For example, this pattern is inefficient:

// Inefficient<br>for (leti = 2; i <= lastRow; i++) {<br>constvalue = sheet.getRange(i, 1).getValue();<br>// ... processing ...<br>sheet.getRange(i, 2).setValue(result);<br>}<br>This more efficient version reads and writes values in bulk:<br>// Efficient<br>constrange = sheet.getRange(2, 1, lastRow - 1, 2);<br>constvalues = range.getValues();<br>for (leti = 0; i < values.length; i++) {<br>constvalue = values[i][0];<br>// ... processing ...<br>values[i][1] = /* result */;<br>}<br>range.setValues(values);

The same idea applies to Gmail, Drive, and external APIs: read data in bulk, process it in memory, and write back in as few calls as possible.

Checklist When You See “Exceeded maximum execution time”

When the error appears, walk through this checklist:

  1. Identify the heaviest API calls
    • Is the script mostly interacting with Sheets, Gmail, Drive, or an external API?
  2. Check for repeated service calls inside loops
    • Are you calling getRange, getValue, or setValue on every iteration?
  3. Reduce the scope if possible
    • Narrow down to a smaller set of rows, messages, or files
  4. Consider batch processing
    • Handle 100–200 items per run instead of thousands
  5. Implement progress tracking and chunked execution
    • Store the current position using PropertiesService or a dedicated cell in the sheet

Following this checklist will help you pinpoint the bottleneck and choose the right mitigation strategy.

Conclusion

In Apps Script, “Exceeded maximum execution time” is less a fatal error and more a signal that your script has outgrown a naive, single-run design. As your data volume and business logic grow, you will eventually hit the platform’s time limits unless you adopt patterns such as:

  • Bulk reads and writes
  • Batch processing
  • Background execution via triggers

By designing with these constraints in mind from the beginning, you can build scripts that remain robust and maintainable even as their workload increases.

References

  1. Handling Script Runtime Limits in Apps Script — https://pulse.appsscript.info/p/2021/08/an-easy-way-to-deal-with-google-apps-scripts-6-minute-limit/
  2. Dealing with Execution Time Limits — https://www.labnol.org/code/20016-maximum-execution-time-limit
  3. Stack Overflow: Exceeded maximum execution time in Google Apps Script — https://stackoverflow.com/questions/72628571/google-apps-script-exceeded-maximum-execution-time
  4. Google Apps Script Quotas and Limits — https://developers.google.com/apps-script/guides/services/quotas

ZIDOOKA!

Need help with the content of this article?

I provide individual technical support related to the issues described in this article, as a freelance developer. If the problem is blocking your work or internal tasks, feel free to reach out.

Support starts from $30 USD (Estimate provided in advance)
Thank you for reading

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

Policy on AI Usage

Some articles on this site are written with the assistance of AI. However, we do not rely entirely on AI for writing; it is used strictly as a support tool.