JavaScript 政策运行时错误问题排查

ScriptExecutionFailed

错误代码

steps.javascript.ScriptExecutionFailed

错误响应正文

{
    "fault": {
        "faultstring": "Execution of javascript_policy_name failed with error: error_type: error_description. (javascript_source_file_name)\"",
        "detail": {
            "errorcode": "steps.javascript.ScriptExecutionFailed"
        }
    }
}

错误类型和可能的原因

JavaScript 政策可能会抛出许多不同类型的 ScriptExecutionFailed 错误。下表列出了一些较为常见的错误:

错误类型 原因
范围错误 如果您使用的数字超出合法值范围,则会抛出 RangeError
引用错误 如果您使用(引用)未声明的变量,则会抛出 ReferenceError
语法错误 如果您尝试使用语法错误来评估代码,则会抛出 SyntaxError
类型错误 如果您使用的操作超出预期类型的范围,则会抛出 TypeError
URI 错误 如果您在 URI 函数中使用非法字符,则会抛出 URIError

范围错误

如果您对某个不在允许的值的集合或范围内时的值执行操作,或将这样的值传递给函数,则会抛出错误类型 RangeError

例如,以下情况可能会引发此错误:

  1. 在某些 Date API 中使用无效日期,例如 2018 年 9 月 31 日。
  2. 您向数字方法(例如 Number.toPrecision()Number.tofixed()Number.toExponential())传递了无效值。例如,假设您在 Number.toPrecision() 方法中传递了一个大值(如 400 或 500),则将出现范围错误。
  3. 您创建了非法长度的数组。

错误响应正文

{
    "fault": {
        "faultstring": "Execution of javascript_policy_name failed with error: Javascript runtime error: \"RangeError: error_description. (javascript_source_file_name:line_number)\"",
        "detail": {
            "errorcode": "steps.javascript.ScriptExecutionFailed"
        }
    }
}

注意:范围错误的诊断和解决方法取决于 JavaScript 政策抛出的确切错误消息。下面提供了几个示例供您参考。

示例 1:日期无效

错误响应正文示例

{
    "fault": {
        "faultstring": "Execution of ParseDate failed with error: Javascript runtime error: \"RangeError: Date is invalid. (ParseDate.js:2)\"",
        "detail": {
            "errorcode": "steps.javascript.ScriptExecutionFailed"
        }
    }
}

诊断

  1. 确定 JavaScript 政策、源文件、发生错误的行号和错误说明。您可以在错误响应的 faultstring 元素中找到所有这些信息。例如,在以下 faultstring 中,JavaScript 政策名称为 ParseDate,JavaScript 源文件为 ParseDate.js,发生错误的行号为 2,错误说明为 Date is invalid

    "faultstring": "Execution of ParseDate failed with error: Javascript runtime error: \"RangeError: Date is invalid. (ParseDate.js:2)\""
    
  2. 查看 JavaScript 源文件(在上述第 1 步中确定),检查错误中指定的行号中是否使用了无效日期,或该行号中使用的变量是否有无效日期。如果使用了无效日期,则会导致此错误。

    下面是一个导致此错误的 JavaScript 源文件示例:

    ParseDate.js

    var date = new Date('2018-09-31T11:19:08.402Z');
    date.toISOString();
    

    在此示例中,行号 2 中使用了变量 date。检查源文件时,您可以看到 date 变量设置的日期 2018-09-31T11:19:08.402Z. 无效,因为九月没有 31 天。

    注意:此示例中使用的 ISO-8601 格式是 YYYY-MM-DDTHH:mm:ss.sssZ

解决方法

确保在 JavaScript 代码中使用 Date API 时,始终使用有效的日期。

要修复上述示例 JavaScript 代码,您可以将日期设置为 Sept 30 2018,如下所示:

var date = new Date('2018-09-30T11:19:08.402Z');
date.toISOString();

示例 2:传递给 Precision API 的数字无效

错误响应正文示例

{
    "fault": {
        "faultstring": "Execution of SetNumberPrecision failed with error: Javascript runtime error: "RangeError: Precision 400 out of range. (SetNumberPrecision.js:2)\"",
        "detail": {
            "errorcode": "steps.javascript.ScriptExecutionFailed"
        }
    }
}

诊断

  1. 确定 JavaScript 政策、源文件、发生错误的行号和错误说明。您可以在错误响应的 faultstring 元素中找到所有这些信息。例如,在以下 faultstring 中,JavaScript 政策名称为 SetNumberPrecision,JavaScript 源文件为 SetNumberPrecision.js,发生错误的行号为 2,错误说明为 Precision 400 out of range.

    "faultstring": "Execution of SetNumberPrecision failed with error: Javascript runtime error: "RangeError: Precision 400 out of range. (SetNumberPrecision.js:2)\""
    
  2. 检查 JavaScript 源文件(在上述第 1 步中确定)。如果错误说明中提到的大值被用在了指定行号中,则会导致此错误。

    下面是一个导致此错误的 JavaScript 源文件示例:

    SetNumberPrecision.js

    var number = 12.3456;
    var rounded_number = number.toPrecision(400);
    print("rounded_number = " + rounded_number);
    

    在本例中,请注意行号 2 中使用了大值 400。由于您无法将精度设置为这么大的数字,因此会收到以下错误:

    "faultstring": "Execution of SetNumberPrecision failed with error: Javascript runtime error: "RangeError: Precision 400 out of range. (SetNumberPrecision.js:2)\""
    

解决方法

确保 toPrecision() 方法中使用的数字在允许的值范围内。

要解决上述 JavaScript 示例的问题,请将有效位数设置为有效值 2:

var number = 12.3456;
var rounded_number = number.toPrecision(2);
print("rounded_number = " + rounded_number);

引用错误

当使用(引用)JavaScript 中未定义的变量或对其进行操作时,会抛出错误类型 ReferenceError

错误响应正文

{
    "fault": {
        "faultstring": "Execution of javascript_policy_name failed with error: Javascript runtime error: \"ReferenceError: variable_name is not defined. (javascript_source_file_name:line_number)\"",
        "detail": {
            "errorcode": "steps.javascript.ScriptExecutionFailed"
        }
    }
}

错误响应正文示例

{
    "fault": {
        "faultstring": "Execution of ComputeTotalPrice failed with error: Javascript runtime error: \"ReferenceError: \"price\" is not defined. (ComputeTotalPrice.js:3)\"",
        "detail": {
            "errorcode": "steps.javascript.ScriptExecutionFailed"
        }
    }
}

诊断

  1. 确定 JavaScript 政策、源文件和引用未定义变量的行号。您可以在错误响应的 faultstring 元素中找到所有这些信息。例如,在以下 faultstring 中,JavaScript 政策名称为 ComputeTotalPrice,对应的源文件为 ComputeTotalPrice.js,发生错误的行号为 3,未定义的变量名称为 price.

    "faultstring": "Execution of ComputeTotalPrice failed with error: Javascript runtime error: \"ReferenceError: \"price\" is not defined. (ComputeTotalPrice.js:3)\""
    
  2. 检查 JavaScript 源文件中的行号并验证是否引用了上述第 1 步中确定的未定义变量。例如,以下 JavaScript 代码在第 3 行中引用了未定义的变量 price,该变量与 faultstring 中的内容匹配:

    ComputeTotalPrice.js

    var item = context.getVariable("request.queryparam.item");
    var quantity = context.getVariable("request.queryparam.quantity");
    var totalprice = parseInt(quantity) * parseInt(price);
    context.setVariable("TotalPrice", totalprice);
    
    
  3. 检查是否在 JavaScript 代码中定义了该特定变量。如果未定义该变量,则会导致此错误。

    上述示例脚本中使用了未声明/定义的 price 变量;因此,您会看到以下错误:

    "faultstring": "Execution of ComputeTotalPrice failed with error: Javascript runtime error: \"ReferenceError: \"price\" is not defined. (ComputeTotalPrice.js:3)\""
    

解决方法

确保 JavaScript 代码中引用的所有变量均已正确定义。

要解决上述 JavaScript 示例的问题,请在使用变量 price 之前定义它。例如:

var item = context.getVariable("request.queryparam.item");
var quantity = context.getVariable("request.queryparam.quantity");
var price = context.getVariable("request.queryparam.price");
var totalprice = parseInt(quantity) * parseInt(price);
context.setVariable("TotalPrice", totalprice);

语法错误

当 JavaScript 引擎遇到不符合该语言语法的令牌或令牌顺序时,或当格式无效的输入被传递给解析器 API(例如 JSON/XML 解析)时,则会抛出错误类型 SyntaxError

例如,如果格式无效或不正确的 JSON 载荷作为输入传递给 JavaScript 政策中使用的 JSON.parse API,则会发生此错误。

错误响应正文

{
    "fault": {
        "faultstring": "Execution of javascript_policy_name failed with error: Javascript runtime error: \"SyntaxError: error_description. (javascript_source_file_name:line_number)\"",
        "detail": {
            "errorcode": "steps.javascript.ScriptExecutionFailed"
        }
    }
}

错误响应正文示例

{
    "fault": {
        "faultstring": "Execution of ParseJSONRequest failed with error: Javascript runtime error: \"SyntaxError: Unexpected token: <. (ParseJSONRequest.js:2)\"",
        "detail": {
            "errorcode": "steps.javascript.ScriptExecutionFailed"
        }
    }
}

诊断

  1. 确定 JavaScript 政策、源文件、发生错误的行号和错误说明。您可以在错误响应的 faultstring 元素中找到所有这些信息。例如,在以下 faultstring 中,JavaScript 政策名称为 ParseJSONRequest,JavaScript 源文件为 ParseJSONRequest.js,发生错误的行号为 2,错误说明为 Unexpected token

    "faultstring": "Execution of ParseJSONRequest failed with error: Javascript runtime error: \"SyntaxError: Unexpected token: <. (ParseJSONRequest.js:2)\""
    
  2. 检查 JavaScript 源文件中的第 2 行(在上述第 1 步中确定)并查看正在执行什么操作。如果在执行 JSON.parse() 函数,则检查传递给它的输入参数。如果输入参数无效或是格式不正确的 JSON,则会导致此错误。

    下面是一个导致此错误的 JavaScript 代码示例:

    var input = context.getVariable("request.content");
    var result = JSON.parse(input);
    

    在此示例中,传递给 API 代理的请求载荷 (request.content) 作为 JSON.parse() 函数的输入。

    以下示例 API 调用展示了请求是如何传递的:

    curl -v "http://<org>-<env>.apigee.net/v1/js-demo" -H "Content-Type: application/json" -X POST -d '<city>Bangalore</city>'
    

    在上述请求中,以下 XML 载荷被传递给 API 代理 <city>Bangalore</city>JSON.parse API 需要收到有效的 JSON,但由于传递的是 XML 载荷,因此它失败并显示以下错误:

    "Execution of ParseJSONRequest failed with error: Javascript runtime error: \"SyntaxError: Unexpected token: <. (ParseJSONRequest.js:2)\""
    

解决方法

确保将有效的输入传递给 JavaScript 代码中使用的解析 API。

要解决上面讨论的示例政策的问题,请按以下所示传递有效的 JSON 载荷请求:

curl -v "http://<org>-<env>.apigee.net/v1/js-demo" -H "Content-Type: application/json" -X POST -d '{"city" : "Bangalore"}'

类型错误

在以下情况下,会抛出错误类型 TypeError

  • 传递到函数的操作数或参数与该运算符或函数预期的类型不兼容。
  • 对 null、未定义或错误的对象调用函数。
  • 从 null、未定义或错误的对象访问属性。

例如,在以下情况下,会抛出类型错误:

  • 您尝试对数字调用 toUpperCase() 函数。这是因为 toUpperCase() 函数只能对字符串对象调用。
  • 您尝试从 null 或未定义的对象读取属性。

错误响应正文

{
    "fault": {
        "faultstring": "Execution of javascript_policy_name failed with error: Javascript runtime error: \"TypeError: error_description. (javascript_source_file_name:line_number)\"",
        "detail": {
            "errorcode": "steps.javascript.ScriptExecutionFailed"
        }
    }
}

示例 1:对错误的对象调用函数

如果您尝试对不受支持的对象调用函数,则会收到此错误。例如,如果您尝试对数字调用 toUpperCase() 函数,则会收到该错误。这是因为 toUpperCase() 函数只能对字符串对象调用。

错误响应正文示例

{
    "fault": {
        "faultstring": "Execution of ConvertToUpperCase failed with error: Javascript runtime error: \"TypeError: Cannot find function toUpperCase in object 100. (ConvertToUpperCase.js:2)\"",
        "detail": {
            "errorcode": "steps.javascript.ScriptExecutionFailed"
        }
    }
}

诊断

  1. 确定 JavaScript 政策、源文件、发生错误的行号和错误说明。您可以在错误响应的 faultstring 元素中找到所有这些信息。例如,在以下 faultstring 中,JavaScript 政策名称为 ConvertToUpperCase,源文件为 ConvertToUpperCase.js,行号为 2,错误说明为“**Cannot find function toUpperCase in object 100.”。

    "faultstring": "Execution of ConvertToUpperCase failed with error: Javascript runtime error: \"TypeError: Cannot find function toUpperCase in object 100. (ConvertToUpperCase.js:2)\""
    

    该错误说明表明您正在对数值为 100 的对象调用函数 toUpperCase()

  2. 检查 JavaScript 源文件并验证您是否在行号 2 中(在第 1 步中确定)对数值为 100 的对象调用了函数 toUpperCase()。如果是,则会导致此错误。

    下面是一个导致此错误的 JavaScript 源文件示例:

    ConvertToUpperCase.js

    var number = 100;
    var result = number.toUpperCase();
    

    在上述 JavaScript 代码中,变量 number 的值设置为 100。随后,对该数字对象调用 toUpperCase()( 函数。由于 toUpperCase() 函数只能对字符串对象调用,因此您会收到以下错误:

    "Execution of ConvertToUpperCase failed with error: Javascript runtime error: \"TypeError: Cannot find function toUpperCase in object 100. (ConvertToUpperCase.js:2)\""
    

解决方法

始终对有效对象使用 toUpperCase() 等函数。

如需更正上述示例,您可以创建一个字符串变量,然后对字符串调用 toUpperCase() 函数:

var text = "Hello Apigee !";
var result = text.toUpperCase();

示例 2:无法读取未定义对象中的属性

如果您尝试访问/读取未定义对象的属性,则会收到此错误。例如,如果您尝试从数组中的对象访问数据,但该对象未定义,则可能会发生此错误。请参阅以下的详细说明。

错误响应正文示例

{
    "fault": {
        "faultstring": "Execution of ParseJSONResponse failed with error: Javascript runtime error: \"TypeError: Cannot read property \"length\" from undefined. (ParseJSONResponse.js:7)\"",
        "detail": {
            "errorcode": "steps.javascript.ScriptExecutionFailed"
        }
    }
}

诊断

  1. 确定 JavaScript 政策、源文件、发生错误的行号和错误说明。您可以在错误响应的 faultstring 元素中找到所有这些信息。例如,在以下 faultstring 中,政策名称为 ParseJSONResponse,源文件为 ParseJSONResponse.js,行号为 6,错误说明为 Cannot read property "length" from undefined

    "faultstring": "Execution of ParseJSONResponse failed with error: Javascript runtime error: \"TypeError: Cannot read property \"length\" from undefined. (ParseJSONResponse.js:6)\""
    

    该错误表明无法从未定义的对象中读取属性 length

  2. 检查 JavaScript 源文件中的行号(在上述第 1 步中确定),并验证对象是否有有效值或该对象是否未定义。您可能需要阅读并理解完整的源文件,才能确定该特定对象是如何定义或产生的,从而确定对象未定义的原因。如果您发现该特定对象确实未定义,并且您正尝试访问该对象的 length 属性,则会导致该错误。

    让我们通过一个示例来更好地理解这个问题:

    1. 假设您从后端服务器收到以下 JSON 响应:

      {
          "cars": [
             { "name":"Toyota", "count": 150 }
             { "name":"Honda", "count": 100 },
             { "name":"Ford", "count": 75 }
          ]
      }
      
    2. 下面是一个示例 JavaScript 源文件,它解析此 JSON 响应并导致上述错误:

      ParseJSONResponse.js

      // Get the JSON response
      var jsonData = context.getVariable("response.content");
      print (jsonData);
      
      // Read the cars array
      for (var i = 0; i < jsonData.cars.length; i++)
        {
        print("name = " + jsonData.cars[i].name);
        print("count = " + jsonData.cars[i].count);
        }
      
    3. 仔细检查该 JavaScript 代码后,您会发现在第 2 行中,response.content 作为常规字符串(用英文引号引起)被读取/存储到变量 jsonData 中。

    4. 由于 jsonData 是常规字符串,因此当您尝试从 jsonData 访问 cars 时,jsonData.cars 将成为未定义的对象。

    5. 之后,如果您尝试从 jsonData.cars(未定义)读取属性 length,则会收到以下错误:

      "faultstring": "Execution of ParseJSONResponse failed with error: Javascript runtime error: \"TypeError: Cannot read property \"length\" from undefined. (ParseJSONResponse.js:6)\""
      

解决方法

确保始终使用相关的 JSON API 以 JSON 对象的形式读取 JSON 数据。

如需解决上述示例 JavaScript 问题,您可以对 response.content 对象使用 JSON.parse() 函数,以将其获取为 JSON 对象。之后,您可以访问 cars 数组并成功遍历该数组。

// Get the JSON response
var data = context.getVariable("response.content");
var jsonData = JSON.parse(data);
print (jsonData);

// Read the cars array
for (var i = 0; i < jsonData.cars.length; i++)
{
    print("name = " + jsonData.cars[i].name);
    print("count = " + jsonData.cars[i].count);
}

URI 错误

如果您在 URI 函数中使用非法字符,则会引发错误类型 URIError。例如,如果您将带有百分比符号的 URI 传递给 decodeURIdecodeURIComponent 函数,则会收到此错误。

错误响应正文

{
    "fault": {
        "faultstring": "Execution of javascript_policy_name failed with error: Javascript runtime error: \"URIError: error_description. (javascript_source_file_name:line_number)\"",
        "detail": {
            "errorcode": "steps.javascript.ScriptExecutionFailed"
        }
    }
}

错误响应正文示例

{
    "fault": {
        "faultstring": "Execution of URIDecode failed with error: Javascript runtime error: \"URIError: Malformed URI sequence. (URIDecode.js:2)\"",
        "detail": {
            "errorcode": "steps.javascript.ScriptExecutionFailed"
        }
    }
}

诊断

  1. 确定 JavaScript 政策、源文件、发生错误的行号和错误说明。您可以在错误响应的 faultstring 元素中找到所有这些信息。例如,在以下 faultstring 中,JavaScript 政策名称为 URIDecode</code,JavaScript 源文件为 URIDecode.js,行号为 2,错误说明为 Malformed URI sequence

    "faultstring": "Execution of URIDecode failed with error: Javascript runtime error: \"URIError: Malformed URI sequence. (URIDecode.js:2)\""
    

    错误说明表明 URIDecode.js 的第 2 行使用了格式不正确的 URI 序列。

  2. 检查 JavaScript 源文件,并验证传递到任何 URI 函数的参数是否包含任何非法字符。如果是,则会导致错误。

    下面是一个导致此错误的 JavaScript 源文件示例:

    URIDecode.js

    var str = "75%-Completed";
    var decoded_str = decodeURIComponent(str);
    context.setVariable("decoded_str", decoded_str);
    

    在上述示例 JavaScript 代码中,传递到 decodeURIComponent() 的变量 str 有一个百分号符号,该符号被视为非法字符;因此,您会收到以下错误:

    "Execution of URIDecode failed with error: Javascript runtime error: \"URIError: Malformed URI sequence. (URIDecode.js:2)\""
    

解决方法

确保 URI 函数中使用的所有字符都是合法以及被允许的。

如需解决上述 JavaScript 示例问题,请对百分比符号进行编码。例如,%25

var str = "75%25-Completed";
var decoded_str = decodeURIComponent(str);
context.setVariable("decoded_str", decoded_str);