Bug Reports
Submit bug reports with device context and file attachments using the Mite SDK.
Bug reports are the core of Mite. Submit them yourself with the hook or the
imperative API, or mount ShakeToReport and let the SDK
handle the whole flow.
Only title and description are required. The SDK enriches every report with
device info, the current identity, and the navigation trail.
Using the hook
import { useBugReport } from '@usemite/sdk'
export default function BugReportScreen() {
const { submitBug, submitting, error } = useBugReport()
const handleSubmit = async () => {
await submitBug({
title: 'App crashes on launch',
description: 'The app shows a white screen and closes immediately.',
steps_to_reproduce: '1. Cold start the app\n2. Wait ~2 seconds',
expected_behavior: 'App should open to the home screen',
actual_behavior: 'App crashes with a white screen',
})
}
return (
<Button onPress={handleSubmit} disabled={submitting} title="Submit" />
)
}submitBug rejects when submission fails, and also exposes the failure on
error. Wrap the call in try/catch if you handle it inline.
A plan quota refusal is the one exception. It does not reject,
because it is an expected state and not a fault. It comes back as ok: false
in the result and on refusal.
Return value
| Field | Type | Description |
|---|---|---|
submitBug | (payload: BugReportPayload) => Promise<SubmitBugResult> | Submit a report |
submitting | boolean | Whether a submission is in flight |
error | Error | null | Last submission error |
lastResponse | SubmitBugReportResponse | null | Response from the last successful submission |
refusal | MiteQuotaRefusal | null | Set when the account is over a plan limit |
reset | () => void | Clear error, lastResponse, and refusal |
Direct API access
The same call is available on the instance:
import { useMite } from '@usemite/sdk'
const mite = useMite()
const result = await mite.submitBug({
title: 'Navigation broken',
description: 'Back button does nothing on the settings screen',
})
if (result.ok) {
console.log(result.report.id) // e.g. 'bug_abc123'
}Every submission resolves to a SubmitBugResult:
type SubmitBugResult =
| {
ok: true
report: SubmitBugReportResponse
/** Set when the attachments did not fit in the storage quota. */
droppedAttachments?: { count: number; refusal: MiteQuotaRefusal }
}
| { ok: false; refusal: MiteQuotaRefusal }
interface SubmitBugReportResponse {
id: string
status: 'NEEDS_TRIAGE'
}New reports always land as NEEDS_TRIAGE. ok: false means the account is over
a plan limit and no report was created.
Changed in 0.3.0. submitBug returned SubmitBugReportResponse before.
Read result.report in place of the old response, after a check on
result.ok. The onSubmitted props of ShakeToReport and
StoreReviewPrompt are unchanged, because they fire only on success.
Payload fields
interface SubmitBugReportPayload {
title: string
description: string
user_identifier?: string
anonymous_id?: string
reporter_name?: string
reporter_email?: string
steps_to_reproduce?: string
expected_behavior?: string
actual_behavior?: string
app_version?: string
device_info?: Record<string, unknown>
environment?: Record<string, unknown>
navigation_trail?: NavigationBreadcrumb[]
attachments?: Array<{ uri: string; type?: string; name?: string }>
}Use environment for free-form context of your own (feature flags, the current
screen, an experiment bucket). Use app_version to tag the report with your
release.
There is no priority field. Priority is assigned during triage in the Mite
dashboard, not by the reporting client — priority, status, assigned_to,
and assignee are stripped from the payload before the request is sent.
What the SDK fills in automatically
You do not need to set these yourself:
anonymous_id— the current anonymous identityuser_identifier— the identified user, when there is onedevice_info— brand, model, OS name and version, memory, CPU architectures, and more, collected viaexpo-devicenavigation_trail— the last screens visited, when breadcrumbs are enabled
Passing any of these explicitly overrides the automatic value for that request.
In anonymous-only mode the SDK sends anonymous_id
only and omits user_identifier, reporter_name, reporter_email, and
device_info.
Attachments
Pass local file URIs. The SDK requests an upload URL, uploads each file, and submits the report referencing the stored files.
await mite.submitBug({
title: 'Layout glitch on the profile tab',
description: 'The avatar overlaps the username at small font scales.',
attachments: [
{ uri: screenshotUri, type: 'image/jpeg', name: 'screenshot.jpg' },
],
})uri is anything fetch() can read — an expo-image-picker result, a
react-native-view-shot capture, or a file:// path. type defaults to the
blob's own MIME type, then image/jpeg.
Attachments cannot be uploaded offline. If a report is queued by the
offline queue, its attachments are dropped and a [Mite]
warning is logged — the report itself is still delivered on retry.
Error handling
submitBug throws when the API key is missing, when the server rejects the
report, or when the network fails. On a network error with the offline queue
enabled, the report is queued for retry and the error is still re-thrown, so
your UI decides what to show:
try {
await mite.submitBug({ title, description })
showToast('Thanks for the report!')
} catch {
showToast(
mite.pendingRequestCount > 0
? "Saved — we'll send it when you're back online."
: 'Could not send your report.',
)
}