Soluciona errores

En esta guía, se explica cómo administrar los errores que se producen cuando se ejecuta un paso del flujo. Puedes especificar si un paso fallido requiere la acción del usuario para resolverse o si se puede volver a intentar.

  • Devuelve un error práctico: Agrega un botón al registro de errores que dirija al usuario a la tarjeta de configuración del paso, lo que le permitirá modificar sus entradas para resolver el error. Para marcar un error como práctico, devuelve AddOnsResponseService.ErrorActionability.ACTIONABLE. Para marcar un error como no procesable, devuelve AddOnsResponseService.ErrorActionability.NOT_ACTIONABLE.
  • Reintenta el paso después de un error: El flujo intenta ejecutar el paso nuevamente hasta 5 veces antes de detenerse. Para marcar un error como uno que se puede volver a intentar, devuelve AddOnsResponseService.ErrorRetryability.RETRYABLE. Para marcar un error que no se puede reintentar, devuelve AddOnsResponseService.ErrorRetryability.NOT_RETRYABLE.

También puedes crear registros de errores personalizados con chips, hipervínculos y texto con estilo para proporcionar a los usuarios un contexto más detallado sobre el error.

Devuelve un error con diálogo de acción

En el siguiente ejemplo, se compila un paso que le solicita al usuario un número negativo. Si el usuario ingresa un número positivo, el paso devuelve un error procesable que le solicita al usuario que corrija su entrada.

El siguiente archivo de manifiesto define las entradas y salidas del paso, y las funciones que se deben llamar para la configuración y la ejecución.

JSON

{
  "timeZone": "America/Toronto",
  "dependencies": {},
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8",
  "addOns": {
    "common": {
      "name": "Retry Errors Example",
      "logoUrl": "https://www.gstatic.com/images/icons/material/system/1x/pets_black_48dp.png",
      "useLocaleFromApp": true
    },
    "flows": {
      "workflowElements": [
        {
          "id": "returnElementError",
          "state": "ACTIVE",
          "name": "Return Element Error Action",
          "description": "To notify the user that some error has occurred",
          "workflowAction": {
            "inputs": [
              {
                "id": "value1",
                "description": "The input from the user",
                "cardinality": "SINGLE",
                "dataType": {
                  "basicType": "STRING"
                }
              }
            ],
            "outputs": [
              {
                "id": "output_1",
                "description": "The output",
                "cardinality": "SINGLE",
                "dataType": {
                  "basicType": "STRING"
                }
              }
            ],
            "onConfigFunction": "onConfiguration",
            "onExecuteFunction": "onExecution"
          }
        }
      ]
    }
  }
}

El siguiente código compila la tarjeta de configuración y controla la lógica de ejecución, incluido el control de errores.

Apps Script

/**
 * Returns a configuration card for the step.
 * This card contains a text input field for the user.
 */
function onConfiguration() {
  let section = CardService.newCardSection()
    .addWidget(CardService.newTextInput()
      .setFieldName("value1")
      .setId("value1")
      .setTitle("Please input negative numbers!"));
  const card = CardService.newCardBuilder().addSection(section).build();
  return card;
}

/**
 * Gets an integer value from variable data, handling both string and integer formats.
 * @param {Object} variableData The variable data object from the event.
 * @return {number} The extracted integer value.
 */
function getIntValue(variableData) {
  if (variableData.stringValues) {
    return parseInt(variableData.stringValues[0]);
  }
  return variableData.integerValues[0];
}

/**
 * Executes the step.
 * If the user input is a positive number, it throws an error and returns an
 * actionable error message. Otherwise, it returns the input as an output variable.
 * @param {Object} e The event object from the workflow.
 */
function onExecution(e) {
  try {
    var input_value = getIntValue(e.workflow.actionInvocation.inputs["value1"]);
    if (input_value > 0) {
      throw new Error('Found invalid positive input value!');
    }

    // If execution is successful, return the output variable and a log.
    const styledText_1 = AddOnsResponseService.newStyledText()
      .setText("Execution completed, the number you entered was: ")
      .addStyle(AddOnsResponseService.TextStyle.ITALIC)
      .addStyle(AddOnsResponseService.TextStyle.UNDERLINE);
    const styledText_2 = AddOnsResponseService.newStyledText().setText(input_value)
      .setFontWeight(AddOnsResponseService.FontWeight.BOLD);

    const workflowAction = AddOnsResponseService.newReturnOutputVariablesAction()
      .setVariables({
        "output_1": AddOnsResponseService.newVariableData().addStringValue(input_value)
      })
      .setLog(AddOnsResponseService.newWorkflowTextFormat()
        .addTextFormatElement(
          AddOnsResponseService.newTextFormatElement().setStyledText(styledText_1)
        ).addTextFormatElement(
          AddOnsResponseService.newTextFormatElement().setStyledText(styledText_2)
        ));

    let hostAppAction = AddOnsResponseService.newHostAppAction().setWorkflowAction(workflowAction);
    return AddOnsResponseService.newRenderActionBuilder().setHostAppAction(hostAppAction).build();

  } catch (err) {
    // If an error occurs, return an actionable error action.
    Logger.log('An error occurred: ' + err.message);

    const workflowAction = AddOnsResponseService.newReturnElementErrorAction()
      // Sets the user-facing error message.
      .setErrorLog(
        AddOnsResponseService.newWorkflowTextFormat()
        .addTextFormatElement(
          AddOnsResponseService.newTextFormatElement().setText("Failed because of invalid input values!"))
      )
      // Makes the error actionable, allowing the user to correct the input.
      .setErrorActionability(AddOnsResponseService.ErrorActionability.ACTIONABLE)
      // Specifies that the error is not automatically retried.
      .setErrorRetryability(AddOnsResponseService.ErrorRetryability.NOT_RETRYABLE);

    let hostAppAction = AddOnsResponseService.newHostAppAction().setWorkflowAction(workflowAction);
    return AddOnsResponseService.newRenderActionBuilder().setHostAppAction(hostAppAction).build();
  }
}

Cómo reintentar el paso después de un error

En el siguiente ejemplo, se compila un paso que simula una falla temporal. Si se produce un error, el paso devuelve un error que se puede volver a intentar, lo que hace que el flujo vuelva a ejecutar el paso.

El archivo de manifiesto define el paso.

JSON

{
  "timeZone": "America/Toronto",
  "dependencies": {},
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8",
  "addOns": {
    "common": {
      "name": "Retry Errors Example",
      "logoUrl": "https://www.gstatic.com/images/icons/material/system/1x/pets_black_48dp.png",
      "useLocaleFromApp": true
    },
    "flows": {
      "workflowElements": [
        {
          "id": "retryError",
          "state": "ACTIVE",
          "name": "Retry an error",
          "description": "Simulates a temporary failure and retries the step.",
          "workflowAction": {
            "inputs": [
              {
                "id": "value1",
                "description": "Any input value",
                "cardinality": "SINGLE",
                "dataType": {
                  "basicType": "STRING"
                }
              }
            ],
            "outputs": [
              {
                "id": "output_1",
                "description": "The output",
                "cardinality": "SINGLE",
                "dataType": {
                  "basicType": "STRING"
                }
              }
            ],
            "onConfigFunction": "onRetryConfiguration",
            "onExecuteFunction": "onRetryExecution"
          }
        }
      ]
    }
  }
}

El siguiente código compila la tarjeta de configuración y controla la lógica de reintento.

Apps Script

/**
 * Returns a configuration card for the step.
 * This card contains a text input field for the user.
 */
function onRetryConfiguration() {
  let section = CardService.newCardSection()
    .addWidget(CardService.newTextInput()
      .setFieldName("value1")
      .setId("value1")
      .setTitle("Enter any value"));
  const card = CardService.newCardBuilder().addSection(section).build();
  return card;
}

/**
 * Executes the step and simulates a transient error.
 * This function fails 80% of the time. When it fails, it returns an
 * error that can be retried.
 * @param {Object} e The event object from the workflow.
 */
function onRetryExecution(e) {
  try {
    // Simulate a transient error that fails 80% of the time.
    if (Math.random() < 0.8) {
      throw new Error('Simulated transient failure!');
    }

    // If execution is successful, return the output variable and a log.
    var input_value = e.workflow.actionInvocation.inputs["value1"].stringValues[0];
    const styledText = AddOnsResponseService.newStyledText()
      .setText(`Execution succeeded for input: ${input_value}`);

    const workflowAction = AddOnsResponseService.newReturnOutputVariablesAction()
      .setVariables({
        "output_1": AddOnsResponseService.newVariableData().addStringValue(input_value)
      })
      .setLog(AddOnsResponseService.newWorkflowTextFormat()
        .addTextFormatElement(
          AddOnsResponseService.newTextFormatElement().setStyledText(styledText)
        ));

    let hostAppAction = AddOnsResponseService.newHostAppAction().setWorkflowAction(workflowAction);
    return AddOnsResponseService.newRenderActionBuilder().setHostAppAction(hostAppAction).build();

  } catch (err) {
    // If a transient error occurs, return an error message saying the step tries to run again.
    Logger.log('A error occurred, trying to run the step again: ' + err.message);

    const workflowAction = AddOnsResponseService.newReturnElementErrorAction()
      // Sets the user-facing error message.
      .setErrorLog(
        AddOnsResponseService.newWorkflowTextFormat()
        .addTextFormatElement(
          AddOnsResponseService.newTextFormatElement().setText("A temporary error occurred. The step will be retried."))
      )
      // Makes the error not actionable by the user.
      .setErrorActionability(AddOnsResponseService.ErrorActionability.NOT_ACTIONABLE)
      // Specifies that the error is automatically retried.
      .setErrorRetryability(AddOnsResponseService.ErrorRetryability.RETRYABLE);

    let hostAppAction = AddOnsResponseService.newHostAppAction().setWorkflowAction(workflowAction);
    return AddOnsResponseService.newRenderActionBuilder().setHostAppAction(hostAppAction).build();
  }
}