Sentry-javascript: Pengecualian Non-Error ditangkap dengan kunci: kesalahan, header, pesan, nama, ok

Dibuat pada 28 Okt 2019  ·  48Komentar  ·  Sumber: getsentry/sentry-javascript

Paket + Versi

  • [x] @sentry/browser
  • [ ] @sentry/node
  • [ ] raven-js
  • [ ] raven-node _(gagak untuk simpul)_
  • [ ] lainnya:
  • [x] @angular/core

Versi: kapan:

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

Keterangan

Saya memiliki pengaturan awal untuk aplikasi Angular dengan ErrorInterceptor global
ini cara kirimnya

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

dan saya mendapatkan ini (pengecualian Non-Error ditangkap dengan kunci: kesalahan, header, pesan, nama, ok) kesalahan lagi dan lagi, dan tidak dapat memahami apa yang salah dari deskripsi dan cara mereproduksinya.

Needs Reproduction

Komentar yang paling membantu

Kami saat ini menggunakan yang berikut untuk mengabaikannya.

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

Semua 48 komentar

Ini berarti bahwa objek yang Anda berikan bukan turunan dari Error yang menyimpan stacktrace di aplikasi Angular.

Anda harus (seperti yang ditunjukkan oleh pesan) menggunakan Sentry.captureException(error.error) atau Sentry.captureException(error.message) tergantung pada kebutuhan Anda.

@kamilogorek oh ok) tnx

@kamilogorek masih mendapatkan kesalahan ini, bahkan dengan ini

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

+1, masih mendapatkan kesalahan ini tidak peduli bagaimana saya mengatakannya.

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",
  ...
}

Saya memutuskan untuk melakukan ini

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;
            }
        });

Terima kasih atas solusinya @gchronos! Saya berharap akan ada perbaikan potensial dalam waktu dekat.

Hanya menimpali untuk mengatakan bahwa saya juga mendapatkan kesalahan ini. Saya menggunakan Angular 8 dan setelah membaca beberapa masalah tentang ini, saya menyadari bahwa mungkin saya tidak menangani kesalahan dengan benar dalam komponen penanganan kesalahan saya. Saya sudah mencoba solusi yang disarankan oleh orang lain yang mendefinisikan pengecualian sebelum diteruskan ke captureException tetapi ini tidak mengurangi kesalahan. Akan sangat bagus jika ada yang bisa memberikan masukan lebih lanjut tentang ini atau saya hanya perlu menggunakan solusi GChronos (Terima kasih!).

+1

+1

Adakah yang bisa memberikan repro yang bisa saya gunakan untuk men-debug ini? Saya mencoba menggunakan aplikasi angular-cli dasar dan saya tidak dapat mereproduksi perilaku ini. Terima kasih!

@kamilogorek Saya yakin Anda dapat memulai proyek Angular 8 baru, dan membuat permintaan http menuju titik akhir yang mengembalikan 500 dan tidak menangkap kesalahan dalam layanan http sehingga menyebar ke Sentry.

Saya dapat bergabung dengan beberapa info lebih lanjut, ini adalah ErrorHandler kami:

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

Dalam pelacakan Sentry kami, kami selalu mendapatkan acara duplikat untuk yang berikut:

  • Object.a Pengecualian Non-Error ditangkap dengan kunci: ...
  • captureException Pengecualian Non-Error ditangkap dengan kunci: ...

(Acara lain dilaporkan oke sebagai satu item dalam daftar)

Kami telah mengumpulkan beberapa ratus peristiwa "Non.Error" ini, dan yang menarik, semuanya memiliki kesamaan berikut:

  • browser.name: Samsung Internet 100%
  • browser: Samsung Internet 9.4 100%

Dan kesalahannya sebagian besar adalah sebagai berikut:

{
  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 saya membuat SentryErrorHandler dapat disuntikkan dan mengimplementasikan ErrorHandler alih-alih meluas dan tidak ada lagi masalah seperti itu untuk saya.
Jadi saya berubah dari

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;
 }
}

ke

@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;
 }
}

Saya memiliki konfigurasi pertama selama 2 tahun tanpa masalah tetapi sejak peningkatan ke Angular 8 saya memiliki beberapa pengecualian penjaga.

@jonathan-payiq apakah Anda bisa mengetahui apa penyebabnya? Atau apakah Anda mengabaikan semua pengecualian Non-Error itu sekarang?

Kami saat ini mengabaikan mereka.
Kami mengetahui dari remah roti bahwa ini terjadi ketika tampilan web/browser berada di latar belakang (tidak terlihat), jadi perbaikan bagi kami adalah mencegah pengambilan terjadi saat halaman tidak terlihat. Rupanya browser Samsung menangani penyegaran jaringan dengan buruk saat di latar belakang.

@jonathan-payiq bagaimana tepatnya Anda mengabaikan mereka? Terima kasih sebelumnya.

Kami saat ini menggunakan yang berikut untuk mengabaikannya.

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

@kamilogorek apakah Anda dapat mereproduksi masalah?

Menutup masalah, karena sepertinya masalah asli telah diselesaikan sebagian atau ada solusi yang berfungsi. Saya lebih suka seseorang membuat masalah baru dengan deskripsi baru jika itu masih menjadi masalah.
Tolong jangan ragu untuk ping saya jika masih relevan, dan saya akan dengan senang hati membuka kembali dan mengerjakannya.
Bersulang!

Ini belum diselesaikan. Saya baru saja mencoba mengintegrasikan Sentry dengan Angular 8 dan menemukan masalah ini.

Saya tidak mengerti bagaimana Sentry bisa mengklaim di luar pengaturan kotak, itu sepenuhnya salah.

Saya tidak mengerti bagaimana Sentry bisa mengklaim di luar pengaturan kotak, itu sepenuhnya salah.

@Rush memberikan kasus yang dapat direproduksi, di mana Anda menjelaskan dan menunjukkan apa yang salah, dan kemudian kami dapat memverifikasi klaim Anda.

@kamilogorek Sejujurnya, itu tidak bekerja dengan Angular sejak lebih dari 6 bulan, ada cukup banyak laporan di sini untuk mengonfirmasinya, jadi IMO tidak perlu untuk kasus repro lebih lanjut, Anda dapat menemukannya sendiri dengan cukup mudah. Saya tahu sendiri tidak, karena kami memiliki masalah yang sama dalam proyek kami menggunakan Angular v8, dan sekarang v9 (tidak ada peta sumber).

Tepat, dan selain itu saya membayar Sentry untuk melakukan pekerjaan untuk saya. Ini bukan proyek open source di mana saya berharap tangan saya kotor.

Saya suka Sentry tapi saya bisa mencari alternatif...

Saya menggunakan aplikasi https://github.com/gothinkster/angular-realworld-example-app sebagai contoh, hanya agar semua orang juga dapat melakukan reproduksi yang sama.

Aplikasi kloning Barebone, mengikuti dokumen Sudut Sentry dan mengunggah peta sumber. Berikut adalah hasilnya.


Contoh 1: Logika rusak

Apa yang Angular berikan kepada Anda dalam penangan kesalahan + peristiwa apa yang kami tangkap:

Screenshot 2020-04-16 at 12 01 13

Tampilannya di UI:

Screenshot 2020-04-16 at 12 07 02

Catatan: Semuanya ada di tempatnya, Anda dapat dengan mudah menunjuk ke baris kode yang benar yang rusak, pesan kesalahan dan jenis kesalahan sudah benar, karena Angular memberi Anda objek Error utuh untuk dikerjakan.


Contoh 2: Panggilan layanan rusak

Apa yang Angular berikan kepada Anda dalam penangan kesalahan + acara apa yang kami tangkap:

Screenshot 2020-04-16 at 12 00 49

Tampilannya di UI:

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

Catatan: Tidak ada cara untuk mengetahui jenis kesalahan apa yang telah terjadi, karena Angular tidak memberi Anda informasi ini. Namun, Anda dapat melihat data serial untuk mengetahui, bahwa ada kesalahan "404 Not Found", yang _kemungkinan besar_ berasal dari panggilan XHR yang tidak valid. Kemudian, Anda dapat menyelidiki alur remah roti untuk melihat bahwa _pada kenyataannya_ ada panggilan XHR ke url yang diberikan (yang dalam hal ini berisi kesalahan ketik), didahului dengan klik pada elemen DOM yang tepat, yang memicunya. Dengan informasi ini, seharusnya sudah cukup dalam 99% kasus untuk memperbaiki masalah.


Kami hanya dapat bekerja dengan apa yang telah diberikan kepada kami oleh kerangka kerja. Jika tidak, kita harus menambal kerangka kerja itu sendiri.

Kami hanya dapat bekerja dengan apa yang telah diberikan kepada kami oleh kerangka kerja. Jika tidak, kita harus menambal kerangka kerja itu sendiri.

Apakah ini cara Anda mengatakan "bukan masalah kita"? Sebelum beralih ke penjaga (dari beberapa pesaing) kesalahan XHR ini ditangkap dengan baik dan mereka menggunakan metode pemasangan yang sama dengan penangan kesalahan sudut.

@kamilogorek sebagai vendor Anda juga bisa membuka tiket dengan kerangka kerja. Saya yakin itu akan mendapat perhatian.

Sebelum beralih ke penjaga (dari beberapa pesaing) kesalahan XHR ini ditangkap dengan baik dan mereka menggunakan metode pemasangan yang sama dengan penangan kesalahan sudut.

@szechyjs maka akan sangat bagus jika Anda dapat membagikan solusinya, karena ini adalah SDK sumber terbuka dan kami dapat mengulangi peningkatan jika kami tahu apa yang kami tuju.

... Anda juga bisa membuka tiket dengan kerangka kerja. Saya yakin itu akan mendapat perhatian.

Saya baru saja membuka tiket dengan dukungan penjaga dan merujuk masalah ini.

Seorang pejalan kaki di sini. Untuk kasus saya, saya ingin melaporkan penolakan yang ditangani dalam reaksi asli dan saya akhirnya melihat kesalahan yang sama dengan OP. Sejak the object you provide is not an instance of Error , saya berkeliling menggunakan yang di bawah ini.

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
}

Lalu aku menelepon

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

dan saya melihat

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

Semoga ini membantu!

Dalam kasus saya, bagian Breadcrumbs dari Sentry banyak membantu saya untuk menentukan penyebabnya. Itu sebagian besar terjadi ketika ada sekitar 404 di beberapa API eksternal.

Pembaruan dokumen dan perubahan JS SDK yang diperlukan akan datang:

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

Itu harus dirilis minggu ini! :)

Perbaikan mudah untuk ini (karena ini hanya terjadi dengan kesalahan penyadapan 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;
 }

Dokumen baru dan 5.16.0 baru saja dirilis - https://docs.sentry.io/platforms/javascript/angular/
Saya mencoba membuatnya sejelas dan sedetail mungkin, dan itulah mengapa "mungkin terlihat" seperti banyak kode.

@kamilogorek Saya juga mengalami masalah ini di aplikasi Vue. Apakah ada perbaikan di sana?

Sama disini. pengecualian dilemparkan ke dalam penangan kesalahan integrasi penjaga vuejs.
https://sentry.io/share/issue/eaf13a2455e04150aaaab595d0d7bafe/

@sblawrie masalah apa sebenarnya yang Anda miliki? Beberapa detail lebih lanjut akan membantu.
@cincauhangus sepertinya di suatu tempat dalam kode Anda, Anda membuat kesalahan dengan instance janji itu sendiri (perhatikan kunci abort, always, catch, done ).

Sesuatu seperti:

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

Jadi errorHandler dari Vue mendapatkan seluruh objek janji, di mana ia diharapkan menjadi instance Error .

@kamilogorek terima kasih atas klarifikasinya. Saya telah membuat beberapa perubahan dan akan memantau jika masih menjadi masalah.

Menggunakan Angular 8 dan memiliki masalah pengecualian Non-Error yang sama. Modifikasi contoh kode 'extractError' sebagai berikut:

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;
  }

Dimodifikasi saya Sentry.init beforeSend berdasarkan @untilinvite 's contoh beforeSend di atas. Perubahan ini untuk menangani pesan log kedua dari https://github.com/getsentry/sentry-javascript/issues/2169 juga diselesaikan sebagai Non-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;
        }
      });

Kami telah membuat perubahan yang ditambahkan ke dokumen dengan rilis 5.16.0 dan kami masih mendapatkan kesalahan Non-Error exception captured with keys: error, headers, message, name, ok . Saya berharap paket @sentry/angular akan memperbaiki masalah ini?

Sudut: v9.1
Penjaga: v5.20

@szechyjs apakah Anda juga membaca bagian kedua tentang pencegat http? Ini biasanya masalah utama yang menutupi kesalahan agar tidak terdeteksi dengan benar - https://docs.sentry.io/platforms/javascript/angular/

@szechyjs apakah Anda juga membaca bagian kedua tentang pencegat http? Ini biasanya masalah utama yang menutupi kesalahan agar tidak terdeteksi dengan benar - https://docs.sentry.io/platforms/javascript/angular/

Kami tidak menggunakan pencegat.

Hai, Saya telah menghabiskan beberapa waktu untuk masalah ini dan menemukan bahwa error.error.message pada kesalahan tipe HttpErrorResponse tidak selalu berisi informasi apa pun. Jika kita melihat konstruktornya, kita akan melihat bahwa Angular menyetel prop pesan pada objek root dan bukan pada ErrorEvent .

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

Dengan mengubah baris ini https://github.com/getsentry/sentry-javascript/blob/8eb72865dcd62ff719441105c7eda28007a07e9d/packages/angular/src/errorhandler.ts#L112
ke

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

penangan kesalahan melanjutkan ke return error.message; dan melemparkan kesalahan yang diharapkan.

Tangkapan bagus @jakkn , terima kasih! Handler yang diperbarui di PR https://github.com/getsentry/sentry-javascript/pull/2903

Saya mengalami masalah ini pada aplikasi Express yang baru saja saya warisi. Tidak tahu bagaimana ini bisa terjadi, tetapi tampaknya terjadi untuk sebagian besar kesalahan yang dilakukan aplikasi, dan saya menggunakan pengaturan Express standar dari dokumen.

misalnya https://sentry.io/share/issue/bfd4f674c10b4b4a8b6a291dde8e2a66/

Saya mengalami kesalahan yang sama, meskipun itu untuk penangan permintaan ekspres dan bukan sudut. Pada dasarnya saya memanggil next dengan pojo alih-alih objek Error. Saya melakukan beberapa hal menyenangkan di penangan kesalahan ekspres saya sendiri untuk mengubahnya menjadi sesuatu yang menarik, tetapi karena middleware permintaan sentryio berjalan lebih dulu, itu tidak mendapatkan kesalahan yang disusun ini.

Pada akhirnya, buat fungsi utilitas yang akan mengubah apa pun yang disediakan menjadi sesuatu yang lebih masuk akal:

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))
  }
}

Saya pikir ini mengacaukan jejak tumpukan, tetapi sebenarnya jika itu adalah pojo yang diteruskan ke ini, toh tidak ada jejak tumpukan.

Dalam contoh kami, sebelum ini diperbaiki, sebagian besar peristiwa yang dilaporkan adalah untuk masalah khusus ini dan karena ini adalah server web simpul yang berjalan lama, remah roti hampir tidak berguna -- dan semua kesalahan disatukan ke dalam satu jenis peristiwa ini.

pengecualian const = error.error || pesan kesalahan || error.originalError || kesalahan;

ini akan mengevaluasi menjadi benar/salah

pengecualian const = error.error || pesan kesalahan || error.originalError || kesalahan;

ini akan mengevaluasi menjadi benar/salah

Tidak mungkin, selagi mungkin. Semuanya bermuara pada "kesalahan" apa yang Anda kirim ke aliran. Tapi bagaimanapun juga, ini harus mencakup semacam informasi yang berguna.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat