Skip to main content

Bug reporting

Beta

This page documents Bugsee React Native SDK 7.x, which is in beta and can change between betas. The stable release is 6.x: see the 6.x documentation. Upgrading? See Migrating from 6.x to 7.x.

Bug reports cover something that is wrong but did not crash the app. Your users can raise one with a gesture, or you can open the report dialog, or submit a report silently, from your own code. Crashes and handled errors are covered separately, in Crash & error reporting.

All three calls on this page need a launched SDK; see Before launch.

Built-in report triggers​

The native SDKs can open the report dialog on their own, without any call from your code. These triggers are launch options:

KeyAccessorPlatformsDefaultOpens the report dialog when
com.bugsee.option.reporting.triggers.shakenonebothtrueThe user shakes the device.
com.bugsee.option.reporting.triggers.screenshotnonebothfalseThe user takes a screenshot.
com.bugsee.option.reporting.triggers.notification-bartriggerByNotificationAndroidtrueThe user taps the Bugsee entry in the notification bar.
com.bugsee.option.reporting.triggers.broadcastnoneAndroidfalseAn Android broadcast intent asks for a report.

Turn the shake trigger off, and the screenshot trigger on, at launch:

import Bugsee, { AndroidLaunchOptions, createDefaultLaunchOptions } from '@bugsee/react-native';

const options = createDefaultLaunchOptions();
options.setCustomOption('com.bugsee.option.reporting.triggers.shake', false);
options.setCustomOption('com.bugsee.option.reporting.triggers.screenshot', true);
if (options instanceof AndroidLaunchOptions) {
options.triggerByNotification = false;
}

Bugsee.launch('<your app token>', options);

The Android-only keys are not recognized on iOS, so set them only on an Android options object. The options that shape the dialog itself (required fields, the labels field, the priority selector) are listed under Configuration: Reporting.

Show the report dialog​

Bugsee.showReportDialog(summary?, description?, severity?, labels?) opens the standard reporting UI. Every argument is optional and only pre-fills the form: the user can still edit the values before sending.

import Bugsee, { IssueSeverity } from '@bugsee/react-native';

// An empty form
Bugsee.showReportDialog();

// Pre-fill the summary and description
Bugsee.showReportDialog('Checkout is frozen', 'The spinner never stops.');

// Pre-fill everything, including severity and labels
Bugsee.showReportDialog(
'Checkout is frozen',
'The spinner never stops.',
IssueSeverity.High,
['checkout'],
);

// Severity only: leave the text fields out with undefined
Bugsee.showReportDialog(undefined, undefined, IssueSeverity.Critical);
ArgumentTypeWhen omitted
summarystringThe field is left empty.
descriptionstringThe field is left empty.
severityIssueSeverityThe SDK's default bug severity.
labelsreadonly string[]No labels are pre-filled.

The call returns nothing (void) and does not tell you whether the user sent the report or dismissed the dialog. Subscribe to the BeforeReportShown, AfterReportShown and upload lifecycle events to follow it.

The dialog runs your report handler's onBeforeReportCreated before it opens; see Report handler.

Silent upload​

Bugsee.upload(summary, description, severity?, labels?) creates a bug report and uploads it at once, without any UI. Use it when you have already collected the details in your own UI.

import Bugsee, { IssueSeverity } from '@bugsee/react-native';

Bugsee.upload('Checkout frozen', 'Spinner never stops');

Bugsee.upload('Checkout frozen', 'Spinner never stops', IssueSeverity.High, ['checkout']);

summary and description are required, and both must be strings; an empty string is accepted. An omitted severity gets the default bug severity, com.bugsee.option.reporting.defaults.bug-priority (High unless you set it), on both platforms. An omitted labels sends no labels.

Like showReportDialog, upload returns void. Follow the upload with the BeforeReportUploaded, AfterReportUploaded and ReportUploadFailed* lifecycle events.

warning

Do not call upload from automated error paths. To report an error from code, use Bugsee.logException: an error report carries the stack trace and is grouped with the other occurrences of the same error.

Argument checks​

upload and showReportDialog check their arguments in JavaScript and throw synchronously, before anything reaches the native SDK:

ArgumentRuleThrown
summary, descriptionA string (required for upload, optional for showReportDialog).TypeError
severityOmitted, or an integer from 1 to 5 (an IssueSeverity value).TypeError for a non-number, RangeError for any other number
labelsOmitted, or an array of strings. The array is copied.TypeError
a fifth argumentupload takes at most four arguments. 7.x has no includeVideo.TypeError

labels is still an argument of both calls; only Bugsee.logException lost its per-call labels in 7.x (see Crash & error reporting).

Build a report yourself​

When you need to fill a report over time, attach files to it, or decide when it is sent, use Bugsee.createReport(). It resolves to a BugseeCreatedReport that you fill and then send with its own upload():

import Bugsee, { IssueSeverity } from '@bugsee/react-native';

// React Native's default TypeScript config has no DOM types, so declare the
// global btoa the runtime provides (or use a base64 library).
declare function btoa(data: string): string;

async function reportCheckoutProblem(logText: string): Promise<void> {
const report = await Bugsee.createReport();
if (report === null) {
return; // The SDK made no report: it is not launched.
}
await report.update({
summary: 'Checkout frozen',
description: 'The spinner never stops.',
severity: IssueSeverity.High,
labels: ['checkout'],
attributes: { cartSize: 3 },
});
await report.addDataAttachment(btoa(logText), {
name: 'checkout.log',
mimeType: 'text/plain',
});
const uploaded = await report.upload();
console.log('report handed off:', uploaded);
}

btoa encodes only Latin-1 text; encode other text to bytes first, or use a base64 library.

createReport() resolves null when the SDK made no report, for example before launch. The created report has these methods, each returning a promise:

MethodResolves toDescription
read()BugseeReportSnapshotThe report's current fields; see The snapshot.
update(patch)voidChanges summary, description, severity, labels and attributes in one call; see Changing a report.
addFileAttachment(path, { name, mimeType? })voidAttaches a file. The file is copied when it is added; there is no move option on a created report.
addDataAttachment(base64, { name, mimeType? })voidAttaches bytes, given as a base64 string.
upload()booleanHands the report to the SDK for upload.

The patch, the snapshot and the attachment arguments are the same as on a report handler's report, which has the details. A created report has no id, no type and no deadline: it stays open until you upload it.

One created report at a time​

Only one created report can be outstanding. A second createReport() before the first is uploaded rejects with a BugseeReportError whose code is E_REPORT_CREATE_BUSY. There is no call that discards a created report, so always finish one with upload(); the slot is otherwise freed only when the JavaScript runtime reloads. On iOS the slot stays taken until that upload has completed, so a createReport() made while the previous upload is still in progress also rejects.

upload() ends the report. Every later call on it, including a second upload(), rejects with E_REPORT_HANDLE_DEAD, whatever the upload's result was. Call createReport() again for another report.

What upload() resolves to differs by platform:

  • Android: the result the SDK reports for the upload.
  • iOS: always true, once the report is handed off, even when the SDK is not launched. It does not tell you whether the upload succeeded.

Platform differences​

AndroidiOS
Attachments on a created reportUp to 1000.At most 3, each non-empty and at most 3 MiB. A further or larger one rejects with E_REPORT_ATTACHMENT_REJECTED. mimeType is ignored.
When the report handler runsonBeforeReportCreated runs inside createReport(), onAfterReportCreated at upload().Both callbacks run at upload(), after the created report's fields are copied, so a handler's setLabels replaces the labels you set.

Before launch​

Before launch, upload and showReportDialog do nothing, and createReport() resolves null. Nothing is queued for later.

On iOS, a call made while the SDK is still starting (status Launching) is held and replayed once it is Launched; see A resolved launch is not live capture.

Errors​

Created-report operations reject with a BugseeReportError for the codes below; match on its code, a ReportErrorCode value. Any other failure, such as an unexpected native fault, rejects with an ordinary error, so rethrow what you do not match.

ReportErrorCodecodeMeaning
CreateBusyE_REPORT_CREATE_BUSYAnother created report is still outstanding.
HandleDeadE_REPORT_HANDLE_DEADThe report was already uploaded.
AttachmentRejectedE_REPORT_ATTACHMENT_REJECTEDThe attachment was declined.
BadArgumentE_REPORT_BAD_ARGUMENTAn argument failed validation; nothing was sent.
import Bugsee, { BugseeReportError, ReportErrorCode } from '@bugsee/react-native';

async function openReport() {
try {
return await Bugsee.createReport();
} catch (error) {
if (error instanceof BugseeReportError && error.code === ReportErrorCode.CreateBusy) {
return null; // Finish the outstanding report first.
}
throw error;
}
}

Default severities​

A report gets a default severity unless one is passed or set from a report handler. Change the defaults with these launch options:

KeyDefaultApplies to
com.bugsee.option.reporting.defaults.crash-priorityIssueSeverity.BlockerCrash reports
com.bugsee.option.reporting.defaults.error-priorityIssueSeverity.HighError reports
com.bugsee.option.reporting.defaults.bug-priorityIssueSeverity.HighBug reports
import Bugsee, { IssueSeverity, createDefaultLaunchOptions } from '@bugsee/react-native';

const options = createDefaultLaunchOptions();
options.setCustomOption('com.bugsee.option.reporting.defaults.bug-priority', IssueSeverity.Medium);

Bugsee.launch('<your app token>', options);

Severity values​

IssueSeverity values: VeryLow (1), Medium (2), High (3), Critical (4), Blocker (5). Pass the constants rather than numbers; see the enum reference.

Found an issue, typo, or wrong statement on this page? Report it now →