Error handling
Built-in error shell, error codes, retry, and custom handling in @moviie/player-expo.
Built-in error shell
MoviieVideo renders a built-in error state automatically: no extra setup required. When useMoviiePlayer resolves an error, the shell cross-fades in with:
- A per-code heading and description (in Portuguese)
- A CTA button: either retry (re-triggers the playback fetch) or external (opens
https://app.moviie.ai)
const moviie = useMoviiePlayer({ embedId })
// error shell renders automatically: no conditionals needed
<MoviieVideo {...moviie} aspectRatio={16 / 9} />If playback is already cached when a subsequent fetch fails, the player stays visible and the error shell is not shown: playback is not interrupted.
Error codes
Each error carries a code field and maps to a typed class exported from @moviie/player-sdk.
| Code | Class | When it occurs | Default CTA |
|---|---|---|---|
auth | MoviieAuthError | Invalid or missing publishable key (mvi_pub_*). | Open dashboard |
not_found | MoviieNotFoundError | The embed ID does not exist or was deleted. | Open dashboard |
bundle_blocked | MoviieBundleBlockedError | The app's bundle ID is not in the embed's allowlist. Common on mobile. | Open dashboard |
referrer_blocked | MoviieReferrerBlockedError | Request origin is present but not in the embed's referrer allowlist. More common on web. | Open dashboard |
direct_access_blocked | MoviieDirectAccessBlockedError | The video was opened directly (no embedding origin) while direct-URL access is blocked for the video. | Open dashboard |
subscription_inactive | MoviieSubscriptionInactiveError | Organization subscription is paused or expired. | Open dashboard |
network | MoviieNetworkError | Network request failed (timeout, unreachable, etc.). High relevance on mobile. | Retry |
rate_limit | MoviieRateLimitError | Too many requests in a short period. | Retry |
unknown | Error (fallback) | Any unrecognized error. | Retry |
Accessing the error
useMoviiePlayer exposes error and isLoading alongside the rest of the playback state:
const { error, isLoading, playback, ...moviie } = useMoviiePlayer({ embedId })
if (error) {
console.log(error.code) // e.g. "bundle_blocked"
console.log(error.message) // human-readable message
}Detecting specific errors
import {
MoviieAuthError,
MoviieBundleBlockedError,
MoviieNetworkError,
} from "@moviie/player-sdk"
if (error instanceof MoviieAuthError) {
// invalid key: check EXPO_PUBLIC_MOVIIE_PUBLISHABLE_KEY
}
if (error instanceof MoviieBundleBlockedError) {
// bundle ID not in allowlist: configure it in the Moviie dashboard
}
if (error instanceof MoviieNetworkError) {
// transient: retry is appropriate
}Or match by .code string:
if (error?.code === "bundle_blocked") {
// ...
}Custom retry
By default the Retry CTA re-triggers useMoviiePlayer's internal fetch. Override with onRetry on MoviieVideo:
<MoviieVideo
{...moviie}
aspectRatio={16 / 9}
onRetry={() => {
// e.g. invalidate cache, log analytics, then call the internal retry
moviie.retry()
}}
/>Pass only onRetry to replace the built-in retry entirely (the internal retry() is not called unless you call it yourself). Omit onRetry to use the default behaviour.
Bundle ID allowlist (bundle_blocked)
MoviieBundleBlockedError is the most common mobile-specific error. The SDK sends the app's bundle ID on every playback request (x-moviie-client: bundle_id=…); if the embed's allowlist does not include it, the API rejects the request.
Fix: add your bundle ID under Settings → Embed → Allowed bundles in the Moviie dashboard, or leave the allowlist empty to allow all bundles.
getErrorDisplay utility
@moviie/player-expo exports getErrorDisplay if you need the same per-code copy outside the built-in shell:
import { getErrorDisplay } from "@moviie/player-expo"
const display = getErrorDisplay(error)
// display.code → "bundle_blocked"
// display.heading → "Aplicativo não autorizado"
// display.description → "Este aplicativo não está autorizado a reproduzir este vídeo."
// display.ctaKind → "external" | "retry" | "none"
// display.ctaLabel → "Ajustar permissões"
// display.externalUrl → "https://app.moviie.ai"