Compartir vía


Gestión de errores

Nota

El comportamiento que se describe en este artículo solo está disponible cuando se activa la característica Administración de errores de nivel de fórmula (versión preliminar) a través de Configuración>Próximas características>Versión preliminar. Más información: Controlar qué características están habilitadas.

Siempre hay errores: las redes se caen, el almacenamiento se llena y entran valores inesperados. Es importante que su lógica siga funcionando correctamente cuando hay problemas.

De forma predeterminada, los errores entran a través de las fórmulas de una aplicación y se notifican al usuario final de la aplicación. De esta manera, el usuario final sabe que ha pasado algo inesperado y puede solucionar el problema por sí mismo con una entrada diferente o informar de este al propietario de la aplicación.

Como creador de aplicaciones, está en su mano controlar los errores en su aplicación:

  • Detección y gestión del error. Si existe la posibilidad de que ocurra un error, las fórmulas de la aplicación se pueden escribir de tal forma que se detecte la condición de error y la operación se vuelva a intentar. El usuario final no necesita preocuparse de que se haya producido un error, ya que el creador ha tenido en cuenta esa posibilidad. Esto se hace con las funciones IfError, IsError e IsErrorOrBlank dentro de una fórmula.
  • Informes sobre el error. Si el error no se resuelve en la fórmula en la que se ha encontrado, se traslada al controlador App.OnError, donde el error ya no se puede reemplazar porque ya ha ocurrido y forma parte de los cálculos de la fórmula. Sin embargo, puede usar App.OnError para controlar cómo se informa sobre el error al usuario final, lo que incluye suprimir por completo dicho informe. App.OnError también proporciona un cuello de botella común para el informe de errores en toda la aplicación.
  • Creación y relanzamiento de un error. Finalmente, puede detectar una condición de error con su propia lógica, una condición que sea específica de su aplicación. Use la función Error para crear errores personalizados. La función Error también se utiliza para relanzar un error tras ser interrogado en IfError o App.OnError.

Introducción

Vamos a empezar con un ejemplo sencillo.

  1. Cree una nueva pantalla en una aplicación de lienzo de Power Apps.
  2. Introduzca un control TextInput. De manera predeterminada, tendrá el nombre TextInput1.
  3. Introduzca un control Label.
  4. Establezca la propiedad Text de este control Label en la fórmula
1/Value( TextInput1.Text )

Banner de error que se muestra con

Tenemos un error porque el texto predeterminado de un control TextInput es "Text input", que no se puede convertir a un número. De forma predeterminada, esto es algo positivo: el usuario final recibirá una notificación de que algo no funciona como se esperaba en la aplicación.

Evidentemente, no queremos que el usuario reciba un mensaje de error cada vez que inicia esta aplicación. De todos modos, es probable que "Text input" no sea el mejor valor predeterminado para el cuadro de entrada de texto. Para solucionar esto, vamos a cambiar la propiedad Predeterminada del control TextInput a lo siguiente:

Blank()

Banner de error que se muestra con

Vaya, ahora tenemos un error diferente. Las operaciones matemáticas con blank, como la división, forzarán el valor blank a cero, y eso genera ahora un error de división por cero. Para remediar esto, debemos decidir cuál es el comportamiento apropiado para esta situación en la aplicación. La respuesta puede ser mostrar blank cuando la entrada de texto es blank. Podemos lograr esto si contenemos nuestra fórmula dentro de la función IfError:

IfError( 1/Value( TextInput1.Text ), Blank() )

No se muestra ningún banner de error, un error debido a un valor en blanco se reemplazó con un valor en blanco

Ahora, el error se reemplaza con un valor válido y el mensaje de error desaparece. Lo que pasa es que a lo mejor nos hemos pasado de la raya: IfError abarca todos los errores, lo que incluye escribir un valor incorrecto, como "hello". Podemos solucionar esto ajustando nuestro IfError para que gestione solo la situación de división por cero y relance todos los demás errores:

IfError( 1/Value( TextInput1.Text ), 
         If( FirstError.Kind = ErrorKind.Div0, Blank(), Error( FirstError ) ) )

No se muestra ningún banner de error, un error debido específicamente a la división por cero se reemplazó por un espacio en blanco; de lo contrario, se vuelve a generar el error

Así que, ejecutemos nuestra aplicación y probemos algunos valores diferentes.

Cuando no hay valores, como al iniciar la aplicación, no aparece ninguna respuesta, ya que el valor predeterminado es blank, pero tampoco aparece ningún error, ya que IfError reemplaza el error de división por cero.

No se muestra ninguna respuesta y no hay banner de error

Si introducimos un 4, obtenemos el resultado esperado (0,25):

Se muestra 0,25 y no hay banner de error

Y si escribimos algo no permitido, como hello, recibiremos un mensaje de error:

no se muestra ningún valor y se muestra un banner de error por la imposibilidad de convertir

Este es un ejemplo inicial sencillo. La gestión de errores se puede hacer de muchas maneras diferentes, según las necesidades de la aplicación.

  1. En lugar de un banner de error, podríamos haber mostrado "#Error" en el control de etiqueta con la fórmula. Para mantener los tipos de reemplazos compatibles con el primer argumento de IfError, debemos convertir explícitamente el resultado numérico a una cadena de texto con la función Text.
    IfError( Text( 1/Value( TextInput1.Text ) ), 
             If( FirstError.Kind = ErrorKind.Div0, Blank(), "#Error" )
    
    no hay banner de error y en su lugar se muestra #Error como resultado
  2. En lugar de contener esta instancia específica con IfError, podríamos haber escrito un controlador centralizado App.OnError. No podemos reemplazar la cadena mostrada por "#Error" porque el error ya ha ocurrido y App.OnError solo se ha proporcionado para controlar los informes.
    If( FirstError.Kind <> ErrorKind.Div0, Error( FirstError ) )
    

Propagación de errores

Los errores fluyen a través de fórmulas tal y como ocurre en Excel. Por ejemplo, en Excel, si la celda A1 tiene la fórmula =1/0, A1 mostrará el valor de error #DIV0!:

Una hoja de cálculo de Excel con A1=1/0 y #DIV/0! se muestra en la celda

Si la celda A2 tiene una referencia a A1 con una fórmula como =A1*2, el error también se propaga a través de esa fórmula:

Una hoja de cálculo de Excel con A2=A1*2 y #DIV/0! se muestra en la celda

El error reemplaza al valor que de otro modo se habría calculado. En la celda A2 no encontramos el resultado de la multiplicación, sino solo el error de la división en A1.

Power Fx funciona de la misma manera. En general, si se proporciona un error como argumento de una función u operador, la operación no tendrá lugar y el error de entrada pasará al resultado de la operación. Por ejemplo, Mid( Text( 1/0 ), 1, 1 ) devolverá un error de división por cero, ya que el error más interno pasa a través de la función Text y Mid:

Banner de error que muestra una operación no válida: división por cero

En general, los errores no fluyen a través de las propiedades de control de Power Apps. Ampliemos el ejemplo anterior con un control adicional que muestra si la propiedad Text de la primera etiqueta es un estado de error:

No se muestra ningún error en el control de la segunda etiqueta

Está muy bien que los errores no se propaguen a través de un control porque el sistema observará errores en la entrada de todas las propiedades del control. El error no se perderá.

La mayoría de las funciones y operadores siguen la regla "error en la entrada, error en la salida", pero hay algunas excepciones. Las funciones IsError, IsErrorOrBlank e IfError están diseñadas para trabajar con errores, por lo que es posible que no devuelvan un error aunque reciban uno.

Cómo detectar los errores

Los errores no se detectan hasta que se utiliza su valor.

Como resultado, es posible que las funciones If y Select tampoco devuelvan un error si lo reciben en la entrada. Pongamos como ejemplo la fórmula If( false, 1/0, 3 ). Hay un error de división por cero, pero, como If no va por esa rama debido a false, Power Fx y Power Apps no comunicarán un error:

No se muestra ningún mensaje de error con la función Si en la etiqueta Propiedad de texto

El uso de la función Set con un error no comunicará un error en el punto en el que se coloca el error en la variable. Un ejemplo en Power Apps; una fórmula en App.OnStart que coloca un error de división por cero en la variable x:

No se muestra ningún banner de error con la función Establecer llamada en App.OnStart

No se comunica ningún error porque no se hace referencia a x. Sin embargo, en el momento en que agregamos un control de etiqueta y establecemos su propiedad Text como x, aparece el error:

Banner de error que se muestra con control de etiqueta que hace referencia a la variable x

Puede observar errores dentro de una fórmula con las funciones IfError, IsError e IsErrorOrBlank. Con estas funciones, puede devolver un valor alternativo, tomar una medida alternativa o modificar el error antes de que se detecte y se comunique.

Cómo comunicar un error

Tras observar un error, el siguiente paso es comunicárselo al usuario final.

A diferencia de lo que ocurre en Excel, no siempre hay un lugar conveniente para mostrar un resultado de error, ya que el resultado de una fórmula puede controlar una propiedad, como las coordenadas X e Y de un control, que no dispone de un lugar en el que sea práctico mostrar texto. Cada host de Power Fx determina cómo aparecen los errores para el usuario final y cuánto control tiene el creador sobre este proceso. En Power Apps, aparece un banner de error y se usa App.OnError para controlar cómo se informa sobre el mismo.

Es importante tener en cuenta que App.OnError no puede reemplazar el error tal y como lo hace IfError. Para cuando se ejecuta App.OnError, el error ya ha ocurrido y el resultado se ha propagado a otras fórmulas. App.OnError solo controla cómo se le comunica el error al usuario final y proporciona un enlace para que el creador registre el error si lo desea.

Las variables de ámbito FirstError y AllErrors proporcionan información de contexto sobre los errores. Esto aporta datos sobre el tipo de error, dónde se originó y dónde se ha observado.

Parada después de un error

Las fórmulas de comportamiento admiten la adopción de medidas, la modificación de bases de datos y el cambio de estados. Estas fórmulas permiten tomar más de una medida en una secuencia utilizando el operador de encadenamiento ; (o ;;, según la configuración regional).

En este caso, por ejemplo, el control de cuadrícula muestra lo que hay en la tabla T. Cada selección de botón cambia el estado en esta tabla con dos llamadas Patch:

Animación que muestra los dos registros en la tabla T que se actualizan con números aleatorios después de cada clic en el botón

En una fórmula de comportamiento encadenado, las acciones no se detienen después del primer error. Vamos a modificar nuestro ejemplo para pasar un número de índice no válido en la primera llamada Patch. El segundo Patch continúa a pesar de este error anterior. El primer error se comunica al usuario final y aparece como un error en Studio en el control:

Animación que muestra solo el segundo registro en la tabla T que se actualiza con números aleatorios después de cada clic en el botón, el primer registro genera un error

IfError puede usarse para detener la ejecución después de un error. De un modo similar a lo que ocurre con la función If, el tercer argumento de esta función proporciona un lugar para poner acciones que deben ejecutarse solo si no hay ningún error:

Animación que no muestra cambios en ninguno de los registros de la tabla T, porque IfError impide que se complete la segunda operación después de un error

Si aparece un error durante una de las iteraciones de ForAll, el resto de las iteraciones no se detendrán. ForAll está diseñado para ejecutar cada iteración de forma independiente, lo que permite la ejecución en paralelo. Cuando se completa ForAll, se devolverá un error que contiene todos los errores encontrados (mediante un examen de AllErrors en IfError o App.OnError).

Por ejemplo, la siguiente fórmula dará como resultado que ForAll devuelva dos errores (por la división por cero y por el Value de 0, dos veces) y Collection tendrá tres registros (para cuando Value no sea 0): [1, 2, 3].

Clear( Collection ); 
ForAll( [1,0,2,0,3], If( 1/Value > 0, Collect( Collection, Value ) ) );

Cómo trabajar con varios errores

Una fórmula de comportamiento puede ejecutar más de una acción, así que también puede encontrarse más de un error.

De forma predeterminada, el primer error se le comunica al usuario final. En este ejemplo, las dos llamadas Patch han fallado; la segunda, con un error de división por cero. Al usuario, solo se le muestra el primer error (el del índice):

El primer error de índice se muestra en un banner de error, el segundo error no se nptifica

Las funciones IfError y App.OnError pueden acceder a todos los errores encontrados con la variable de ámbito AllErrors. En este caso, podemos establecer esto en una variable global y observar los dos errores encontrados. En la tabla, aparecen en el mismo orden en el que se encontraron:

Captura de los errores en la variable global PatchErrors, donde podemos ver que ambos errores están presentes

También se pueden devolver múltiples errores en fórmulas que no sean de comportamiento. Por ejemplo, el uso de la función Patch con un lote de registros para actualizar puede devolver varios errores, uno por cada registro que falla.

Errores en tablas

Como hemos visto antes, los errores se pueden almacenar en variables. Los errores también se pueden incluir en estructuras de datos, como tablas. Esto se hace para lograr que un error en un registro no invalide toda la tabla.

Por ejemplo, vamos a analizar este control de tabla de datos en Power Apps:

Tabla de datos que muestra un error para el campo Recíproco para una entrada de 0, lo que da como resultado un error de división por cero

El cálculo en AddColumns ha encontrado un error de división por cero para uno de los valores. Para ese único registro, la columna Reciprocal tiene un valor de error (división por cero), pero los otros registros no lo tienen y están bien. IsError( Index( output, 2 ) ) devuelve falso e IsError( Index( output, 2 ).Value ) devuelve verdadero.

Si ocurre un error al filtrar una tabla, todo el registro es un error, pero se devuelve en el resultado para que el usuario final sepa que ahí había algo y que hay un problema.

Vamos a ver este ejemplo. Aquí, la tabla original no tiene errores, pero el acto de filtrar crea un error cada vez que Value es igual a 0:

Tabla de datos que muestra errores para dos registros que no pudieron ser procesados por los criterios de filtro

Los valores -5 y -3 se filtran correctamente. Los valores 0 dan como resultado un error al procesar el filtro, por lo que no está claro si el registro debe incluirse o no en el resultado. Para maximizar la transparencia para los usuarios finales y ayudar a los creadores en la depuración, incluimos un registro de errores en lugar del original. En este caso, IsError( Index( output, 2 ) ) devuelve verdadero.

Errores de origen de datos

Las funciones que modifican el contenido de los orígenes de datos, como Patch, Collect, Remove, RemoveIf, Update, UpdateIf y SubmitForm informan de los errores de dos maneras:

  • Cada una de estas funciones devolverá un valor de error como resultado de la operación. Los errores se pueden detectar con IsError y se pueden reemplazar o suprimir con IfError y App.OnError, como de costumbre.
  • Después de la operación, la función Errors también devuelve los errores de las operaciones anteriores. Esto puede ser útil para mostrar el mensaje de error en una pantalla de formulario sin necesidad de capturarlo en una variable de estado.

Por ejemplo, esta fórmula buscará un error desde Collect y mostrará un mensaje de error personalizado:

IfError( Collect( Names, { Name: "duplicate" } ),
         Notify( $"OOPS: { FirstError.Message }", NotificationType.Warning ) )

La función Errors también devuelve información sobre errores pasados durante las operaciones de runtime. Esto puede ser útil para mostrar un error en una pantalla de formulario sin necesidad de capturarlo en una variable de estado.

Relanzamiento de errores

A veces, hay algunos errores potenciales esperables y se pueden ignorar sin problemas. Dentro de IfError y App.OnError, si se detecta un error que debe pasarse al siguiente controlador superior, se puede volver a lanzar con Error( AllErrors ).

Cómo crear sus propios errores

También puede crear sus propios errores con la función Error.

Si crea sus propios errores, le recomendamos que use valores superiores a 1000 para evitar posibles conflictos con futuros valores de error del sistema.

Valores de enumeración ErrorKind

Enumeración ErrorKind Valor Descripción
AnalysisError 18 Error del sistema. Ha habido un problema con el análisis del compilador.
BadLanguageCode 14 Se utilizó un código de idioma no válido o no reconocido.
BadRegex 15 Expresión regular no válida. Compruebe la sintaxis utilizada con las funciones IsMatch, Match o MatchAll.
Conflict 6 El registro que se está actualizando ya se modificó en el origen y es necesario resolver el conflicto. Una solución común es guardar los cambios locales, actualizar el registro y volver a aplicar los cambios.
ConstraintViolated 8 El registro no pasó una verificación de restricción en el servidor.
CreatePermission 3 El usuario no tiene permiso para crear registros para el origen de datos. Por ejemplo, se ha llamado a la función Collect.
DeletePermissions 5 El usuario no tiene permiso para eliminar registros para el origen de datos. Por ejemplo, se ha llamado a la función Remove.
Div0 13 División por cero.
EditPermissions 4 El usuario no tiene permiso para crear registros para el origen de datos. Por ejemplo, se ha llamado a la función Patch.
GeneratedValue 9 Se ha pasado erróneamente un valor al servidor para un campo que el servidor calcula automáticamente.
InvalidFunctionUsage 16 Uso no válido de una función. A menudo, uno o más de los argumentos de la función son incorrectos o se utilizan de forma no válida.
FileNotFound 17 No se ha podido encontrar el almacenamiento SaveData.
InsufficientMemory 21 No hay suficiente memoria o almacenamiento en el dispositivo para la operación.
InvalidArgument 25 Se ha pasado un argumento no válido a una función.
Internal 26 Error del sistema. Hubo un problema interno con una de las funciones.
MissingRequired 2 Faltaba un campo obligatorio de un registro.
Network 23 Ha habido un problema con las comunicaciones de red.
None 0 Error del sistema. No hay ningún error.
NotApplicable 27 No hay valores disponibles. Resulta útil para ver la diferencia entre un valor blank, que se puede tratar como cero en cálculos numéricos, y los valores blank que deben marcarse como problema potencial si se usa el valor.
NotFound 7 No se ha encontrado el registro. Por ejemplo, el registro que se debe modificar en la función Patch.
NotSupported 20 Operación no admitida por este reproductor o dispositivo.
Numeric 24 Se ha usado una función numérica de manera incorrecta. Por ejemplo, Sqrt con -1.
QuotaExceeded 22 Cuota de almacenamiento superada.
ReadOnlyValue 10 La columna es de solo lectura y no se puede modificar.
ReadPermission 19 El usuario no tiene permiso de lectura de registros en el origen de datos.
Sync 1 El origen de datos ha notificado un error. Consulte la columna Message para obtener más información.
Unknown 12 Se ha producido un error, pero es de tipo desconocido.
Validation 11 El registro no ha superado una verificación de validación.