MiteSDK

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

FieldTypeDescription
submitBug(payload: BugReportPayload) => Promise<SubmitBugResult>Submit a report
submittingbooleanWhether a submission is in flight
errorError | nullLast submission error
lastResponseSubmitBugReportResponse | nullResponse from the last successful submission
refusalMiteQuotaRefusal | nullSet when the account is over a plan limit
reset() => voidClear 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 identity
  • user_identifier — the identified user, when there is one
  • device_info — brand, model, OS name and version, memory, CPU architectures, and more, collected via expo-device
  • navigation_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.',
  )
}

On this page