Sentry-javascript: Excepción de no error capturada con claves: error, encabezados, mensaje, nombre, ok

Creado en 28 oct. 2019  ·  48Comentarios  ·  Fuente: getsentry/sentry-javascript

Paquete + Versión

  • [x] @sentry/browser
  • [] @sentry/node
  • [] raven-js
  • [] raven-node _ (cuervo por nodo) _
  • [ ] otro:
  • [x] @angular/core

Versión:

5.7.1 (@sentry/browser)
8.2.11 (@angular/core)

Descripción

Tengo una configuración inicial para la aplicación Angular con ErrorInterceptor global
aqui como lo mando

    const eventId = Sentry.captureException(error.originalError || error);
    Sentry.showReportDialog({ eventId });

y obtengo este error (excepción de no error capturada con claves: error, encabezados, mensaje, nombre, ok) una y otra vez, y no puedo entender qué es lo que está mal en la descripción y cómo reproducirlo.

Needs Reproduction

Comentario más útil

Actualmente estamos usando lo siguiente para ignorarlo.

Sentry.init({
  ignoreErrors: [
    'Non-Error exception captured'
  ]
});

Todos 48 comentarios

Esto significa que el objeto que proporcionas no es una instancia de Error que contiene el stacktrace en la aplicación Angular.

Debería (como indica el mensaje) usar Sentry.captureException(error.error) o Sentry.captureException(error.message) según sus necesidades.

@kamilogorek oh ok) tnx

@kamilogorek sigue recibiendo este error, incluso con este

    const exception = error.error || error.message || error.originalError || error;
    const eventId = Sentry.captureException(exception);

+1, sigo recibiendo este error sin importar cómo lo diga.

sentry.error-handler.ts

export class SentryErrorHandler extends GeneralErrorHandler {
  ...
  handleError(error) {
    ...
    const exception = error.originalError || error.error || error
    Sentry.captureException(exception)
  }
}

package.json

{
  ...
  "@angular/core": "^8.2.11",
  "@sentry/browser": "^5.7.1",
  ...
}

Decidí hacer esto

Sentry.init({
            dsn: environment.sentryUrl,
            beforeSend(event, hint) {
                /* tslint:disable:no-string-literal only-arrow-functions */
                const isNonErrorException =
                    event.exception.values[0].value.startsWith('Non-Error exception captured') ||
                    hint.originalException['message'].startsWith('Non-Error exception captured');
                /* tslint:enable:no-string-literal only-arrow-functions */

                if (isNonErrorException) {
                    // We want to ignore those kind of errors
                    return null;
                }
                return event;
            }
        });

¡Gracias por la solución @gchronos! Espero que haya una posible solución pronto.

Solo intervengo para decir que también estoy recibiendo estos errores. Estoy usando Angular 8 y después de leer bastantes problemas sobre esto, me doy cuenta de que podría ser un caso en el que no maneje el error correctamente en mi componente de manejo de errores. Probé las soluciones alternativas sugeridas por otros que definen la excepción antes de pasar a captureException, pero esto no ha reducido los errores. Sería genial si alguien pudiera dar más información sobre esto o simplemente tendré que usar la solución de GChronos (¡Gracias!).

+1

+1

¿Alguien puede proporcionar una reproducción que pueda usar para depurar esto? Intenté usar la aplicación base angular-cli y no puedo reproducir este comportamiento. ¡Gracias!

@kamilogorek Creo que puede iniciar un nuevo proyecto de Angular 8 y hacer una solicitud http hacia un punto final que devuelve 500 y no detectar el error en el servicio http para que se propague a Sentry.

Puedo intervenir con más información, este es nuestro ErrorHandler:

@Injectable()
export class SentryErrorHandler implements ErrorHandler {
  constructor() { }
  handleError(error) {
    Sentry.captureException(error.originalError || error.error || error);
  }
}

En nuestro seguimiento de Sentry siempre obtenemos eventos duplicados para estos:

  • Objeto.a Excepción de no error capturada con claves: ...
  • captureException Excepción sin error capturada con claves: ...

(Otros eventos se informan correctamente como un elemento de la lista)

Hemos recopilado un par de cientos de estos eventos "Sin error" y, curiosamente, todos tienen lo siguiente en común:

  • nombre del navegador: Samsung Internet 100%
  • navegador: Samsung Internet 9.4 100%

Y los errores son principalmente los siguientes:

{
  error: [Object], 
  headers: [Object], 
  message: Http failure during parsing for https://foo.bar/baz, 
  name: HttpErrorResponse, 
  ok: False, 
  status: 200, 
  statusText: OK, 
  url: https://foo.bar/baz
}

Ok, rendericé SentryErrorHandler inyectable e implementa ErrorHandler en lugar de extender y no hay más problemas como ese para mí.
Así que cambié de

export class SentryErrorHandler extends ErrorHandler {

 constructor() {
     super();
 }

 handleError(err: any): void {
     if (environment.production === true || environment.preprod === true) {
         Sentry.captureMessage(err.originalError || err);
     }
     throw err;
 }
}

para

@Injectable()
export class SentryErrorHandler implements ErrorHandler {

 constructor() { }

 handleError(err: any): void {
     if (environment.production === true || environment.preprod === true) {
         Sentry.captureException(err.originalError || err);
     }
     throw err;
 }
}

Tuve la primera configuración durante 2 años sin problemas, pero desde la actualización a Angular 8 tengo varias excepciones de centinela.

@ jonathan-payiq, ¿ha podido averiguar qué causa esto? ¿O simplemente ignora todas esas excepciones sin errores ahora?

Actualmente los estamos ignorando.
A partir de las rutas de navegación, descubrimos que esto ocurre cuando la vista web / navegador está en segundo plano (no visible), por lo que la solución para nosotros es evitar que se produzca la recuperación mientras la página no está visible. Aparentemente, los navegadores Samsung manejan mal la actualización de la red cuando está en segundo plano.

@ jonathan-payiq, ¿exactamente cómo los estás ignorando? Gracias por adelantado.

Actualmente estamos usando lo siguiente para ignorarlo.

Sentry.init({
  ignoreErrors: [
    'Non-Error exception captured'
  ]
});

@kamilogorek , ¿

Cerrando el problema, ya que parece que el problema original se ha resuelto parcialmente o hay una solución que funciona. Preferiría que alguien creara un nuevo problema con una descripción nueva si aún es un problema.
No dude en enviarme un ping si todavía es relevante, y con gusto lo volveré a abrir y trabajaré en él.
¡Salud!

No se ha resuelto. Intenté integrar Sentry con Angular 8 y encontré este problema.

No entiendo cómo puede Sentry reclamar una configuración inmediata, es completamente falso.

No entiendo cómo puede Sentry reclamar una configuración inmediata, es completamente falso.

@Rush proporciona un caso reproducible, donde usted explica y muestra lo que está mal, y luego podemos verificar su reclamo.

@kamilogorek A decir verdad, que no funciona con Angular desde hace más de 6 meses, hay suficientes informes aquí para confirmarlo, por lo que, en mi opinión, no hay necesidad de más casos de reproducción, puede averiguarlo usted mismo con bastante facilidad. Yo mismo sé que no, ya que tenemos el mismo problema en nuestro proyecto usando Angular v8, y ahora v9 (sin mapas de origen).

Exactamente, y además estoy pagando para que Sentry haga el trabajo por mí. No es un proyecto de código abierto en el que espero ensuciarme las manos.

Me gusta Sentry pero podría buscar alternativas ...

Usé una aplicación

Barebone clonó la aplicación, siguió los documentos angulares de Sentry y cargó los mapas de origen. Aquí están los resultados.


Ejemplo 1: lógica rota

Lo que Angular le brinda en un controlador de errores + qué evento capturamos:

Screenshot 2020-04-16 at 12 01 13

Cómo se ve en la interfaz de usuario:

Screenshot 2020-04-16 at 12 07 02

Nota: Todo está en su lugar, puede señalar fácilmente la línea correcta de código que se rompió, el mensaje de error y el tipo de error son correctos, porque Angular le brinda un objeto Error completo para trabajar.


Ejemplo 2: llamada de servicio rota

Lo que Angular le brinda en un controlador de errores + qué evento capturamos:

Screenshot 2020-04-16 at 12 00 49

Cómo se ve en la interfaz de usuario:

Screenshot 2020-04-16 at 12 07 12
Screenshot 2020-04-16 at 12 08 03

Nota: No hay forma de saber qué tipo de error se ha producido, porque Angular no le proporciona esta información. Sin embargo, puede echar un vistazo a los datos serializados para saber que hubo un error "404 No encontrado", que _ muy probablemente_ provino de una llamada XHR no válida. Luego, puede investigar el flujo de migas de pan para ver que _de hecho_ hubo una llamada XHR a la URL dada (que en este caso contenía un error tipográfico), precedida por un clic en un elemento DOM exacto, que lo activó. Con esta información, debería ser suficiente en el 99% de los casos para solucionar el problema.


Solo podemos trabajar con lo que nos ha dado el marco. De lo contrario, tendríamos que parchear el marco en sí.

Solo podemos trabajar con lo que nos ha dado el marco. De lo contrario, tendríamos que parchear el marco en sí.

¿Es esta tu forma de decir "no es nuestro problema"? Antes de cambiar a centinela (de algunos competidores), estos errores XHR se capturaron muy bien y utilizaron el mismo método de instalación con un controlador de errores angulares.

@kamilogorek como proveedor también puede abrir un ticket con el marco. Estoy seguro de que llamará la atención.

Antes de cambiar a centinela (de algunos competidores), estos errores XHR se capturaron muy bien y utilizaron el mismo método de instalación con un controlador de errores angulares.

@szechyjs, entonces sería genial si pudieras compartir la solución, ya que es un SDK de código abierto y podemos iterar sobre las mejoras si sabemos a qué apuntamos.

... también puedes abrir un ticket con el framework. Estoy seguro de que llamará la atención.

Acabo de abrir un ticket con el soporte de centinela y mencioné este problema.

Un transeúnte por aquí. Para mi caso, quiero informar los rechazos manejados en react native y terminé viendo el mismo error que el OP. Desde the object you provide is not an instance of Error , usé lo siguiente.

export interface IError extends Error {
  code?: ErrorCode
  msg?: string
}

export const appError = (code: ErrorCode, msg: string = ''): IError => {
  const errmsg = `code: ${code}, msg: ${msg}`
  const err: IError = new Error(errmsg)
  err.code = code
  err.msg = msg
  err.name = 'appError'
  return err
}

Entonces llamo

export const logError = (err: Error) => {
  sentry.captureException(err)
}

y veo

スクリーンショット 0032-05-24 1 58 38

¡Espero que esto ayude!

En mi caso, la sección Breadcrumbs de Sentry me ayudó mucho a identificar la causa. Ocurrió principalmente cuando había 404 en algunas API externas.

Se acercan la actualización de los documentos y los cambios necesarios en el SDK de JS:

https://github.com/getsentry/sentry-docs/pull/1695/
https://github.com/getsentry/sentry-javascript/pull/2601

¡Debería ser lanzado esta semana! :)

Solución fácil para esto (ya que esto solo sucede con errores interceptados por HTTP):

handleError(error: Error | HttpErrorResponse | any) {
      // ... 
      if (error.constructor.name === "HttpErrorResponse") {
                error.error.Message + " (" + error.message + ")";
                error = error.error;
      }
      // ...
      Sentry.captureMessage(err.originalError || err.error || error);

     throw err;
 }

Se han publicado nuevos documentos y 5.16.0 - https://docs.sentry.io/platforms/javascript/angular/
Traté de hacerlo lo más explícito y detallado posible, y por eso "puede parecer" mucho código.

@kamilogorek También tengo este problema en una aplicación de Vue. ¿Hay alguna solución ahí?

Aquí igual. la excepción se lanza en el controlador de errores de integración de vuejs sentry.
https://sentry.io/share/issue/eaf13a2455e04150aaaab595d0d7bafe/

@sblawrie, ¿qué problema tienes exactamente? Algunos detalles más serían útiles, por favor.
@cincauhangus , parece que en algún lugar de su código está arrojando un error con la instancia de promesa en sí (tenga en cuenta abort, always, catch, done claves).

Algo como:

const promise = new Promise((resolve, reject) => (...));
// somehow somewhere in the code
function foo () {
  // ...
  throw promise
}

Entonces, el errorHandler de Vue está obteniendo un objeto de promesa completo, donde espera ser una instancia Error .

@kamilogorek gracias por la aclaración. Hice algunos cambios y monitorearé si aún es un problema.

Usando Angular 8 y tenía el mismo problema de excepción de no error. Se modificó el código de ejemplo 'extractError' de la siguiente manera:

private static extractError(error: any) {
    // Try to unwrap zone.js error.
    // https://github.com/angular/angular/blob/master/packages/core/src/util/errors.ts
    if (error && error.ngOriginalError) {
      error = error.ngOriginalError;
    }
    // We can handle messages and Error objects directly.
    if (typeof error === 'string' || error instanceof Error) {
      return error;
    }
    // If it's http module error, extract as much information from it as we can.
    if (error instanceof HttpErrorResponse) {
      // The `error` property of http exception can be either an `Error` object, which we can use directly...
      if (error.error instanceof Error) {
        return error.error;
      }
      // ... or an`ErrorEvent`, which can provide us with the message but no stack...
      if (error.error instanceof ErrorEvent) {
        return error.error.message;
      }
      // ...or the request body itself, which we can use as a message instead.
      if (typeof error.error === 'string') {
        return `Server returned code ${error.status} with body "${error.error}"`;
      }
      // If we don't have any detailed information, fallback to the request message itself.
      return error.message;
    }

    // ***** CUSTOM *****
    // The above code doesn't always work since 'instanceof' relies on the object being created with the 'new' keyword
    if (error.error && error.error.message) {
      return error.error.message;
    }
    if (error.message) {
      return error.message;
    }
    // ***** END CUSTOM *****

    // Skip if there's no error, and let user decide what to do with it.
    return null;
  }

Modificado mi Sentry.init beforeSend basado en el ejemplo @untilinvite 's beforeSend anteriormente. Este cambio es para manejar un segundo mensaje de registro de https://github.com/getsentry/sentry-javascript/issues/2169 que también se resuelve como un No Error.

 Sentry.init({
        dsn: AppConfig.envSettings.sentryDSN,
        maxBreadcrumbs: 50,
        environment: this.getEnvName(),
        integrations: [new Sentry.Integrations.Breadcrumbs({ console: false })],
        beforeSend(event, hint) {
          // Note: issue with double entries during http exceptions: https://github.com/getsentry/sentry-javascript/issues/2169
          // Note: issue with a second entry not being set correctly (as a non-error): https://github.com/getsentry/sentry-javascript/issues/2292#issuecomment-554932519
          const isNonErrorException = event.exception.values[0].value.startsWith('Non-Error exception captured');
          if (isNonErrorException) {
            if (!event.extra.__serialized__) {
              return null;
            }
            let realErrMsg = event.extra.__serialized__.error ? event.extra.__serialized__.error.message : null;
            realErrMsg = realErrMsg || event.extra.__serialized__.message;
            // this is a useless error message that masks the actual error.  Lets try to set it properly
            event.exception.values[0].value = realErrMsg;
            event.message = realErrMsg;
          }
          return event;
        }
      });

Hemos realizado los cambios que se agregaron a los documentos con la versión 5.16.0 y todavía recibimos errores Non-Error exception captured with keys: error, headers, message, name, ok . Espero que el paquete @ sentry / angular solucione estos problemas.

Angular: v9.1
Centinela: v5.20

@szechyjs , ¿también leíste la segunda parte sobre los interceptores http? Este suele ser el problema principal que provoca que el error no se detecte correctamente: https://docs.sentry.io/platforms/javascript/angular/

@szechyjs , ¿también leíste la segunda parte sobre los interceptores http? Este suele ser el problema principal que provoca que el error no se detecte correctamente: https://docs.sentry.io/platforms/javascript/angular/

No estamos usando interceptores.

Hola, dediqué un tiempo a este problema y descubrí que error.error.message en errores de tipo HttpErrorResponse no contiene necesariamente ninguna información. Si miramos el constructor, veremos que Angular establece la propiedad del mensaje en el objeto raíz y no en ErrorEvent .

https://github.com/angular/angular/blob/cb3db0d31b91bea14c7f567fe7e7220b9592c11b/packages/common/http/src/response.ts#L345

Al cambiar esta línea https://github.com/getsentry/sentry-javascript/blob/8eb72865dcd62ff719441105c7eda28007a07e9d/packages/angular/src/errorhandler.ts#L112
para

if (error.error instanceof ErrorEvent && error.error.message)

el manejador de errores procedió a return error.message; y arrojó el error esperado.

Gran captura @jakkn , ¡gracias! Controlador actualizado en el PR https://github.com/getsentry/sentry-javascript/pull/2903

Tengo este problema en una aplicación Express que acabo de heredar. No tengo idea de cómo podría suceder esto, pero parece estar sucediendo para la mayoría de los errores que arroja la aplicación, y estoy usando la configuración Express estándar de los documentos.

por ejemplo, https://sentry.io/share/issue/bfd4f674c10b4b4a8b6a291dde8e2a66/

Encontré este mismo error, aunque fue para el controlador de solicitud expresa y no angular. Básicamente, estaba llamando a next con un pojo en lugar de un objeto Error. Hago algunas cosas divertidas en mi propio controlador de errores express para convertirlo en algo de interés, pero debido a que el middleware de solicitud de sentryio va primero, no obtuvo este error calculado.

Al final, creó una función de utilidad que convertiría todo lo que se proporcionara en algo más razonable:

export const handleMaybeError = err => {
  if (err instanceof Error) return err
  const newErr = new Error(err.message || 'unexpected')
  for (const [key, value] of Object.entries(err)) {
    newErr[key] = value
  }
  return newErr
}

export const someController = (req, res, next) => {
  try {
    await handleResponse(req, res)
  } catch (err) {
    next(handleMaybeError(err))
  }
}

Creo que esto cambia los rastros de la pila, pero realmente si se trataba de un pojo pasado a esto, no había ningún rastro de la pila de todos modos.

En nuestro caso, antes de que se solucionara esto, la gran mayoría de los eventos informados fueron por este problema en particular y debido a que es un servidor web de nodo de larga duración, las rutas de exploración son casi inútiles, y todos los errores se agrupan en este tipo de evento.

excepción constante = error.error || error.message || error.originalError || error;

esto se evaluará como verdadero / falso

excepción constante = error.error || error.message || error.originalError || error;

esto se evaluará como verdadero / falso

Improbable, aunque posible. Todo se reduce a qué "error" envía en la corriente. Pero después de todo, esto debería incluir algún tipo de información útil.

¿Fue útil esta página
0 / 5 - 0 calificaciones