Revclust
DocsPricing
Log inStart free
DocsPricingLog inStart free

Start Here

  • Overview
  • Access and Setup
  • Getting Started

Integration

  • Integrate the SDK
  • Trigger Your First Incident

Verification

  • Verify and Observe

Viewer

  • Viewer Workflow

Help

  • Troubleshooting

Reference

  • SDK Reference

Documentation

Verify and Observe

Use status, upload activity, and upload events to confirm the first accepted incident.

Check Status

RevclustStatusWhat it means for the integration
disabledThe SDK has not been initialized in this app process yet.
initializingSetup is still in progress.
readyThe SDK is ready to capture and upload.
degradedSetup is unhealthy but not fully broken. Upload connectivity may be down, or local capture may have failed during startup.
uploadBlockedThe SDK can still queue locally, but it cannot upload right now.
misconfiguredThe SDK key is missing, malformed, or otherwise invalid for bootstrap.
notProvisionedThe SDK key is well-formed but unavailable or revoked.

captureInvariantFailure(...) is always allowed in ready and uploadBlocked. In degraded, it only works if the problem is upload connectivity. If local capture failed during startup, captureInvariantFailure(...) is still blocked. It is always blocked in disabled, initializing, misconfigured, and notProvisioned.

Check Upload Activity

uploadSnapshot.pendingCount tells you how many captures are waiting to upload. uploadSnapshot.uploadingCount tells you how many captures are actively uploading, and uploadSnapshot.lastErrorCode gives the best-known coarse queue or upload error after a failure. A first healthy run usually moves from one queued capture to one active upload and then back to zero.

final RevclustUploadSnapshot snapshot = revclust.uploadSnapshot;

final int pendingCount = snapshot.pendingCount;
final int uploadingCount = snapshot.uploadingCount;
final RevclustUploadErrorCode? lastErrorCode = snapshot.lastErrorCode;

Watch Upload Events

RevclustUploadStarted means a queued capture has started uploading. RevclustUploadAccepted means the backend accepted it. RevclustUploadRejected means the backend rejected it. RevclustTransportFailure means upload failed before the backend could accept or reject it.

revclust.uploadEvents.listen((RevclustUploadEvent event) {
  if (event is RevclustUploadAccepted) {
    final RevclustAcceptedResult result = event.result;
    final String packId = result.packId;
    final Uri? viewerUrl = result.viewerUrl;
  }

  if (event is RevclustUploadRejected) {
    final RevclustRejectionCode code = event.code;
    final String? message = event.message;
  }

  if (event is RevclustTransportFailure) {
    final int? statusCode = event.statusCode;
    final bool retryable = event.retryable;
    final String? message = event.message;
  }
});

Use One Simple First-Pass Observer

For the first pass, use one simple loop: subscribe before capture, keep the returned captureId, replay any early events, ignore unrelated captures, and stop waiting after a clear timeout.

import "dart:async";
import "package:flutter/foundation.dart";
import "package:revclust_flutter_sdk/revclust_flutter.dart";

Future<void> verifyFirstAcceptedIncident({
  required Revclust revclust,
  required RevclustInvariantFailure failure,
}) async {
  debugPrint("Revclust status=${revclust.status.name}");

  final Completer<void> finished = Completer<void>();
  final List<RevclustUploadEvent> bufferedEvents = <RevclustUploadEvent>[];
  String? captureId;

  void finish() {
    if (!finished.isCompleted) {
      finished.complete();
    }
  }

  void handleEvent(RevclustUploadEvent event) {
    final String? activeCaptureId = captureId;
    if (activeCaptureId == null) {
      bufferedEvents.add(event);
      return;
    }

    if (event.captureId != activeCaptureId) {
      return;
    }

    if (event is RevclustUploadAccepted) {
      debugPrint("Accepted packId=${event.result.packId}");
      debugPrint("Accepted viewerUrl=${event.result.viewerUrl}");
      finish();
      return;
    }

    if (event is RevclustUploadRejected) {
      debugPrint("Rejected code=${event.code} message=${event.message}");
      finish();
      return;
    }

    if (event is RevclustTransportFailure && !event.retryable) {
      debugPrint(
        "Transport failure statusCode=${event.statusCode} message=${event.message}",
      );
      finish();
    }
  }

  late final StreamSubscription<RevclustUploadEvent> subscription;
  subscription = revclust.uploadEvents.listen(handleEvent);

  try {
    final RevclustCaptureOutcome outcome =
        await revclust.captureInvariantFailure(failure);
    debugPrint("Immediate capture outcome=${outcome.runtimeType}");

    if (outcome is! RevclustCaptureQueued) {
      return;
    }

    captureId = outcome.captureId;
    for (final RevclustUploadEvent event
        in List<RevclustUploadEvent>.of(bufferedEvents)) {
      handleEvent(event);
    }
    bufferedEvents.clear();

    await finished.future.timeout(const Duration(seconds: 30), onTimeout: () {
      final RevclustUploadSnapshot snapshot = revclust.uploadSnapshot;
      debugPrint("Timed out waiting for acceptance");
      debugPrint("pending=${snapshot.pendingCount}");
      debugPrint("uploading=${snapshot.uploadingCount}");
      debugPrint("lastErrorCode=${snapshot.lastErrorCode}");
    });
  } finally {
    await subscription.cancel();
  }
}

Keep that observer next to the shared Revclust client. If you do not see an accepted event within thirty seconds, move to Troubleshooting.

What Success Looks Like

Success looks like this: Revclust.initialize(...) returns a client, status settles at ready, the first invariant failure returns RevclustCaptureQueued, upload activity drains back to zero, and uploadEvents emits RevclustUploadAccepted. Open the incident page with the direct incident link (viewerUrl) or the incident ID (packId).

When To Stop And Fix Setup

Stop and fix setup if status stays at misconfigured or notProvisioned, the first invariant failure returns RevclustCaptureBlocked, uploadSnapshot.lastErrorCode stays non-null after repeated attempts, you see RevclustUploadRejected, or you have an accepted packId but the right Revclust account still cannot open it.

If the happy path does not complete, include the visible status, the immediate capture result, lastErrorCode, and any upload event code in your report.

On this page

  1. Check Status
  2. Check Upload Activity
  3. Watch Upload Events
  4. Use One Simple First-Pass Observer
  5. What Success Looks Like
  6. When To Stop And Fix Setup
TermsPrivacy Policy