Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
993 views
in Technique[技术] by (71.8m points)

debugging - How to solve common errors in Google Apps Script development

The Q&A is currently a subject of meta discussion, do participate. The current plan is to split where possible into Q&As. Answers to the A&A are community wiki and the question should become one when the status is resolved.


Preface

This Q&A strives to become a collection and a reference target for common errors encountered during development in Google Apps Script language in hopes to improve long-term maintainability of tag.

There are several similar and successful undergoings in other languages and general-purpose tags (see c++, android, php, php again), and this one follows suit.


Why it exists?

The amount of questions from both new and experienced developers regarding the meaning and solutions to errors encountered during development and production that can be effectively reduced to a single answer is substantial. At the time of writing, even running a query only by language tag yields:

Linking to a most relevant duplicate is hard and time-consuming for volunteers due to the need to consider nuances and often poorly-worded titles.


What it consists of?

Entries in this Q&A contain are designed to provide info on how to:

  • parse the error message structure
  • understand what the error entails
  • consistently reproduce (where applicable)
  • resolve the issue
  • provide a link to canonical Q&A (where possible)

Table of Contents

To help you navigate the growing reference please use the TOC below:

  1. General errors
  2. Service-specific errors

What this is not?

The scope of the Q&A is limited to common (not trivial). This is not:

  • a catch-all guide or "best practices" collection
  • a reference for general ECMAScript errors
  • GAS documentation
  • a resources list (we have a tag wiki for that)

What to add?

When adding an entry, please, consider the following:

  • is the error common enough (see "why" section for examples)?
  • can the solution be described concisely and be applicable for most cases?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Preface

The answer provides a guide on general errors that can be encountered when working with any Google service (both built-in and advanced) or API. For errors specific to certain services, see the other answer.

Back to reference


General errors


Message

TypeError: Cannot read property 'property name here' from undefined (or null)

Description

The error message indicates that you are trying to access a property on an Object instance, but during runtime the value actually held by a variable is a special data type undefined. Typically, the error occurs when accessing nested properties of an object.

A variation of this error with a numeric value in place of property name indicates that an instance of Array was expected. As arrays in JavaScript are objects, everything mentioned here is true about them as well.

There is a special case of dynamically constructed objects such as event objects that are only available in specific contexts like making an HTTP request to the app or invoking a function via time or event-based trigger.

The error is a TypeError because an "object" is expected, but "undefined" is received

How to fix

  1. Using default values
    Logical OR || operator in JavaScript has an intersting property of evaluating the right-hand side iff the left-hand is falsy. Since objects in JS are truthy, and undefined and null are falsy, an expression like (myVar || {}).myProp [(myVar || [])[index] for arrays] will guarantee that no error is thrown and the property is at least undefined.

    One can also provide default values: (myVar || { myProp : 2 }) guarantees accessing myProp to return 2 by default. Same goes for arrays: (myVar || [1,2,3]).

  2. Checking for type
    Especially true for the special case, typeof operator combined with an if statement and a comparison operator will either allow a function to run outside of its designated context (i.e. for debugging purposes) or introduce branching logic depending on whether the object is present or not.

    One can control how strict the check should be:

  • lax ("not undefined"): if(typeof myVar !== "undefined") { //do something; }
  • strict ("proper objects only"): if(typeof myVar === "object" && myVar) { //do stuff }

Related Q&As

  1. Parsing order of the GAS project as the source of the issue

Message

Cannot convert some value to data type

Description

The error is thrown due to passing an argument of different type than a method expects. A common mistake that causes the error is accidental coercion of a number to string.

How to reproduce

function testConversionError() {
  const ss = SpreadsheetApp.getActiveSheet();
  ss.getRange("42.0",1);
}

How to fix

Make sure that the value referenced in the error message is of data type required by documentation and convert as needed.


Message

Cannot call Service and method name from this context

Description

This error happens on a context mismatch and is specific to container-bound scripts. The primary use case that results in the error is trying to call a method only available in one document type (usually, getUi() as it is shared by several services) from another (i.e. DocumentApp.getUi() from a spreadsheet).

A secondary, but also prominent case is a result of calling a service not explicitly allowed to be called from a custom function (usually a function marked by special JSDoc-style comment @customfunction and used as a formula).

How to reproduce

For bound script context mismatch, declare and run this function in a script project tied to Google Sheets (or anything other than Google Docs):

function testContextMismatch() {
  const doc = DocumentApp.getUi();
}

Note that calling a DocumentApp.getActiveDocument() will simply result in null on mismatch, and the execution will succeed.

For custom functions, use the function declared below in any cell as a formula:

/**
 * @customfunction
 */
function testConversionError() {
  const ui = SpreadsheetApp.getUi();
  ui.alert(`UI is out of scope of custom function`);
}

How to fix

  1. Context mismatch is easily fixed by changing the service on which the method is called.
  2. Custom functions cannot be made to call these services, use custom menus or dialogs.

Message

Cannot find method Method name here

The parameters param names do not match the method signature for method name

Description

This error has a notoriously confusing message for newcomers. What it says is that a type mismatch occurred in one or more of the arguments passed when the method in question was called.

There is no method with the signature that corresponds to how you called it, hence "not found"

How to fix

The only fix here is to read the documentation carefully and check if order and inferred type of parameters are correct (using a good IDE with autocomplete will help). Sometimes, though, the issue happens because one expects the value to be of a certain type while at runtime it is of another. There are several tips for preventing such issues:

  1. Setting up type guards (typeof myVar === "string" and similar).
  2. Adding a validator to fix the type dynamically thanks to JavaScript being dynamically typed.

Sample

/**
 * @summary pure arg validator boilerplate
 * @param {function (any) : any}
 * @param {...any} args
 * @returns {any[]}
 */
const validate = (guard, ...args) => args.map(guard);

const functionWithValidator = (...args) => {
  const guard = (arg) => typeof arg !== "number" ? parseInt(arg) : arg;

  const [a,b,c] = validate(guard, ...args);
  
  const asObject = { a, b, c };
  
  console.log(asObject);
  
  return asObject;
};

//driver IIFE
(() => {
  functionWithValidator("1 apple",2,"0x5");
})()

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...