Pular para o conteúdo

Erros

Tabela completa de códigos de erro, classes e tratamento recomendado.

  1. Programático: use instanceof (Web) ou when/switch por tipo (Android/iOS) para tratamento específico
  2. Código numérico: use error.code (Web) ou error.type (nativos) para tratamento granular
  3. Serialização: error.toJSON() (Web) retorna objeto sem stack trace — seguro para telemetria
  4. Causa raiz: error.cause (Web) ou error.exception (Android) preserva o erro original

CódigoConstanteClasseQuando ocorre
1000UNKNOWNProvviErrorErro genérico não classificado
2001CAMERA_NOT_SUPPORTEDProvviUserAgentErrorBrowser não suporta getUserMedia
3001STREAM_OPEN_FAILEDProvviStreamErrorFalha ao abrir câmera (permissão negada, câmera em uso)
3002STREAM_CAPTURE_FAILEDProvviStreamErrorFalha ao capturar frame (canvas, encoding JPEG)
4001SESSION_FETCH_FAILEDProvviAPIErrorSessão não encontrada, expirada ou já capturada
4002INGEST_FAILEDProvviAPIErrorErro no envio da captura (rejeição do servidor)
5001CAPTURE_FAILEDProvviCaptureErrorErro na orquestração do pipeline
5002TOKEN_REQUIREDProvviCaptureErroropen() chamado sem token
6001GPS_UNAVAILABLEProvviGeolocationErrorAPI de geolocalização não disponível
6002GPS_DENIEDProvviGeolocationErrorUsuário negou permissão de localização
6003GPS_TIMEOUTProvviGeolocationErrorTimeout na aquisição de GPS
7001UPLOAD_FAILEDProvviUploadErrorFalha no upload da captura
8001LICENSE_KEY_MISSINGProvviLicenseErrorlicenseKey não informada
8002LICENSE_INVALIDProvviLicenseErrorLicença rejeitada — código genérico, ver details.reason abaixo
8003LICENSE_NETWORK_ERRORProvviLicenseErrorFalha de rede na validação

O código LICENSE_INVALID (8002) cobre múltiplas situações. O motivo específico é acessível via error.details.reason (Web) ou pelo campo reason na resposta de /validate:

details.reasonSituação
INVALID_KEYChave não encontrada no banco
REVOKEDLicença desativada pelo administrador
EXPIREDContrato expirado
VOLUME_EXCEEDEDLimite mensal de capturas atingido
CLIENT_SUSPENDEDConta do cliente suspensa
PACKAGE_NOT_ALLOWEDBundle/package não autorizado para esta licença
import { EVENTS, ProvviLicenseError, ProvviStreamError, CODES } from 'provvi-camera.es.js';
camera.addEventListener(EVENTS.ERROR, (e) => {
const err = e.detail.error;
// Por classe
if (err instanceof ProvviLicenseError) {
// err.details.reason → INVALID_KEY, REVOKED, EXPIRED, etc.
showLicenseError(err.details.reason);
return;
}
if (err instanceof ProvviStreamError) {
showCameraError(err.message);
return;
}
// Por código numérico
switch (err.code) {
case CODES.TOKEN_REQUIRED:
console.error('Token não fornecido');
break;
case CODES.GPS_DENIED:
showGpsWarning();
break;
default:
reportToSentry(err.toJSON());
}
});

TipoDescriçãoRecuperável
Permissões
PERMISSION_DENIEDCâmera ou localização negadaSim — solicitar novamente
Integridade
DEVICE_COMPROMISEDRoot/emulador detectadoNão
STRONGBOX_UNAVAILABLEStrongBox ausente (não bloqueante)N/A
ATTESTATION_ERRORPlay Integrity API inacessívelSim — retry
Câmera
CAMERA_NOT_FOUNDSem câmera físicaNão
CAMERA_IN_USECâmera em uso por outro appSim — fechar outro app
CAMERA_TIMEOUTSem frame em 10 segundosSim — retry
CAMERA_ERRORErro genérico de câmeraSim — retry
Localização
MOCK_LOCATION_DETECTEDGPS falso detectadoNão
LOCATION_UNAVAILABLESem fonte de localizaçãoDepende do perfil
Recaptura
RECAPTURE_SUSPECTEDFoto de tela detectadaNão
Assinatura
SIGNING_FAILEDFalha C2PA (c2pa-rs)Sim — retry
MANIFEST_INVALIDManifesto corrompidoSim — retry
FRAME_HASH_FAILEDFalha SHA-256Sim — retry
Rede
NETWORK_UNAVAILABLESem conectividadeSim — verificar rede
BACKEND_UNAVAILABLEUpload falhouSim — retry via retryUpload()
BACKEND_AUTH_FAILEDAPI Key inválida (401)Verificar credenciais
BACKEND_TIMEOUTTimeout no uploadSim — retry
TSA_UNAVAILABLETimestamp Authority offlineSim — retry automático (3x)
Relógio
CLOCK_SUSPICIOUSDrift > 300s (cliente) ou > 600s (servidor)Não
Licenciamento
LICENSE_KEY_MISSINGlicenseKey vazio no configConfigurar a chave
LICENSE_NOT_VALIDATEDvalidateLicense() não chamadoChamar antes de capture()
LICENSE_INVALIDChave não reconhecidaVerificar no Admin Console
LICENSE_REVOKEDLicença revogadaContatar Provvi
LICENSE_EXPIREDContrato expiradoRenovar contrato
LICENSE_VOLUME_EXCEEDEDLimite mensal atingidoAmpliar volume
LICENSE_NETWORK_ERRORSem rede para validarVerificar conexão
LICENSE_CLIENT_SUSPENDEDConta suspensaContatar Provvi
LICENSE_PACKAGE_NOT_ALLOWEDPackage não autorizadoVerificar licença
Genérico
UNKNOWNErro não classificadoDepende
when (outcome) {
is CaptureOutcome.LicenseError -> {
when (outcome.error.type) {
ProvviErrorType.LICENSE_EXPIRED -> showRenewDialog()
ProvviErrorType.LICENSE_VOLUME_EXCEEDED -> showUpgradeDialog()
ProvviErrorType.LICENSE_REVOKED -> blockCapture()
else -> showGenericError(outcome.error.message)
}
}
is CaptureOutcome.BackendError -> {
when (outcome.errorType) {
BackendErrorType.TSA_UNAVAILABLE -> scheduleRetry(outcome.result)
BackendErrorType.AUTH_FAILED -> checkCredentials()
else -> showRetryDialog(outcome.message)
}
}
// ...
}

CasoEnumDescrição
Chave vazia.keyMissinglicenseKey não configurado
Chave inválida.invalidKey("INVALID_KEY")Não encontrada no backend
Revogada.invalidKey("REVOKED")Desativada pelo admin
Expirada.invalidKey("EXPIRED")Contrato vencido
Volume excedido.invalidKey("VOLUME_EXCEEDED")Limite mensal
Conta suspensa.invalidKey("CLIENT_SUSPENDED")Cliente suspenso
Rede.networkError(error)Falha de rede + sem cache válido
switch outcome {
case .licenseError(let reason):
switch reason {
case "EXPIRED": showRenewDialog()
case "VOLUME_EXCEEDED": showUpgradeDialog()
case "REVOKED", "CLIENT_SUSPENDED": blockCapture()
default: showAlert("Licença: \(reason)")
}
case .backendError(let message, let session):
if let session = session {
// Captura local OK — agendar retry
scheduleRetry(session)
}
case .deviceCompromised:
showAlert("Dispositivo comprometido. Captura bloqueada.")
// ...
}

HTTPEndpointCausaBody
400/web/sessionsPayload inválido{ "error": "Payload inválido: ..." }
400/web/sessionsProfile inválido{ "error": "profile inválido — use: ..." }
400/web/ingestImagem estática{ "error": "Imagem estática detectada..." }
401/web/sessionsAPI Key inválida{ "error": "API key inválida ou ausente" }
403/web/ingestClock drift > 600s{ "error": "Relógio do dispositivo fora de sincronia..." }
404/web/sessions/:tokenSessão não encontrada{ "error": "Sessão não encontrada" }
409/web/ingestHash duplicado (replay){ "error": "Imagem duplicada detectada na sessão" }
410/web/sessions/:tokenSessão expirada{ "error": "Sessão expirada ou já utilizada" }
502/web/ingestErro na assinatura{ "error": "Erro de assinatura: ..." }

Quando /validate retorna { "valid": false, "reason": "..." }:

ReasonDescriçãoAção recomendada
INVALID_KEYChave não encontrada no bancoVerificar chave no Admin Console
REVOKEDLicença desativada pelo adminContatar Provvi
EXPIREDData de expiração do contrato ultrapassadaRenovar contrato
VOLUME_EXCEEDEDCapturas excederam o limite mensalAguardar reset ou ampliar volume
CLIENT_SUSPENDEDConta do cliente suspensaContatar Provvi
PACKAGE_NOT_ALLOWEDBundle/package não está na whitelistRegistrar package no Admin Console