Saltar al contenido
dte-sdk

Errores y códigos de estado

Toda falla que el SDK lanza a propósito es un DteError con un code estable. Tú decides según el código y lees el contexto desde details; nunca interpretas el mensaje. Esta página lista cada código, qué lo lanza y qué suelen traer sus details, y luego cubre los códigos de estado del SII (envío, recepción, documento, reclamos y cedibilidad), que se devuelven como dato y no se lanzan.

Usar DteError#

TypeScript
import { createDocument, DteError, errorCode, isDteError } from 'dte-sdk'
 
try {
  createDocument({ ...input, items: [{ name: 'x'.repeat(81), unitPrice: 1 }] })
} catch (error) {
  if (isDteError(error)) {
    error.code // 'FIELD_TOO_LONG'
    error.message // 'Field exceeds the maximum length allowed by the SII schema (field=NmbItem, maxLength=80, length=81)'
    error.details // { field: 'NmbItem', maxLength: 80, length: 81, value: 'xxxxxxxx…' }
  }
}
ExportQué hace
DteErrorLa clase de error. code es un DteErrorCode, details es un registro de solo lectura con contexto.
isDteError(value)Guarda de tipo: true cuando value es un DteError.
errorCode(value)El código cuando value es un DteError, si no undefined. Útil cuando reportas fallas como dato.
DTE_ERROR_CODESEl objeto con todos los códigos: DTE_ERROR_CODES.INVALID_RUT === 'INVALID_RUT'.
DteErrorCode, DteErrorDetailsLos tipos del código y de los detalles.
isRetryableError(value)True para los errores que merecen otro intento. Ver Reintentos.

details frente a message#

El mensaje es genérico y seguro de registrar: es una frase fija por código, seguida de una lista corta de claves de detalle seguras, es decir, nombres de campo, códigos y números. Nunca incluye RUT, nombres, texto de ítems, URL ni cuerpos de respuesta. Las claves seguras son field, maxLength, length, type, folio, from, to, kind, index, status, httpStatus, code, attempts, channel, operation, trackId, expected, actual, rejection, step, module, day, listed y covered.

Todo lo demás vive solo en details: el valor ofensivo, un RUT, un extracto de respuesta (con tokens y semillas tachados), la URL que se llamó. Trata details como sensible: no lo envíes completo a un log ni a un rastreador de errores. Elige las claves que necesitas (error.details.field, error.details.status).

TypeScript
logger.error('upload failed', { code: error.code, status: error.details.status }) // bien
logger.error('upload failed', error.details) // puede traer RUT, un extracto de respuesta, el valor ofensivo

Códigos de error#

Los códigos están agrupados por tema. Los "details típicos" son las claves que el código suele traer; una operación puede agregar más (todo error de transporte trae además operation).

Validación de entradas#

CódigoSe lanza cuandoDetails típicos
INVALID_RUTUn RUT está mal formado o su dígito verificador es incorrecto. Lo lanza toda función que recibe un RUT.field
INVALID_DOCUMENT_TYPEEl tipo de documento no está soportado. También: un tipo fuera de 33, 34 y 43 en el registro de reclamos, fuera de BOOK_DOCUMENT_TYPES en un libro, fuera de 39 y 41 en un reporte de consumo de folios, una no guía en guideEntryFromDocument.field, type, index
INVALID_FOLIOUn folio no es un entero positivo (libros: hasta 10 dígitos). En un reporte de consumo de folios, un folio repetido entre las líneas.field, folio, type, index
INVALID_DATEUna fecha no es AAAA-MM-DD, un período no es AAAA-MM, o una fecha de libro está fuera de 2000 a 2050.field
INVALID_AMOUNTUn monto no es un número finito (libros: no es un entero seguro, o es negativo donde el esquema lo prohíbe).field, index
MISSING_FIELDFalta un campo u opción obligatorios: por ejemplo companyRut en una llamada sin valor por defecto en el cliente, cover.notificationFolio en un libro especial.field
FIELD_TOO_LONGUn texto excede el largo máximo del esquema del SII (por ejemplo 80 caracteres para el nombre de un ítem).field, maxLength, length, value
INVALID_OPTIONUna opción tiene un valor inválido: un environment o channel desconocido, un timeout no positivo, un trackId incorrecto, una semilla que no son dígitos, un fileName no seguro, una zona de libro que no calza con su envío…field, a veces index
ENCODING_UNSUPPORTED_CHARUn texto contiene un carácter fuera de ISO-8859-1, así que no se puede enviar ni timbrar.index, codePoint

CAF y folios#

CódigoSe lanza cuandoDetails típicos
CAF_INVALIDEl XML del CAF no se puede leer o no es lo que debe ser un CAF. parseCaf y verifyCafSignature también rechazan un DOCTYPE, y parseCaf un texto con más de un <CAF o </CAF y un CAF cuya llave privada no es el par de su clave pública (reason: 'RSASK is not the pair of RSAPK'). Una FRMA vacía ya no es CAF_INVALID: verifyCafSignature responde invalid.reason
CAF_EXPIREDEl CAF pasó los 6 meses desde su fecha de autorización; se lanza al timbrar.type, authorizationDate
CAF_TYPE_MISMATCHEl CAF es de otro tipo de documento que el que estás timbrando.type, cafType
CAF_ISSUER_MISMATCHEl CAF pertenece a otro RUT emisor que el del documento.type
FOLIO_OUT_OF_RANGEEl folio está fuera del rango del CAF, o un registro de folios o el asignador de folios de certificación se quedan sin folios.folio, from, to, type

Certificado#

CódigoSe lanza cuandoDetails típicos
CERT_INVALIDEl PKCS#12 o el PEM no se puede leer, no trae llave privada o certificado, o la llave no corresponde al certificado.reason
CERT_PASSWORD_WRONGLa contraseña del PKCS#12 es incorrecta.ninguno
CERT_EXPIREDEl certificado venció.expiresAt
CERT_NOT_YET_VALIDEl certificado aún no está vigente: su notBefore todavía no llega.validFrom

XML y firmas#

CódigoSe lanza cuandoDetails típicos
XML_PARSE_FAILEDUn XML no se puede interpretar, un elemento a firmar no tiene ID, o falta la raíz o la etiqueta de cierre esperada. verifyReceivedDocuments también la lanza para un DOCTYPE, un sobre sin exactamente un SetDTE y un DTE o Documento con prefijo. Todo DOM que parsea el SDK rechaza con ella los elementos anidados a más de 100 niveles, antes de que algo los recorra.field, reason, root, line, column
SIGNATURE_NOT_FOUNDSe verifica una firma en un XML que no tiene Signature (o SignedInfo).field
ENVELOPE_EMPTYUn sobre no tiene documentos.kind o field
ENVELOPE_KIND_MISMATCHUn documento no corresponde a este tipo de sobre (una boleta en un EnvioDTE, o una factura en un EnvioBOLETA).kind, type
BOOK_TOTAL_MISMATCHCon strictTotals, el total explícito de una línea de libro difiere de la fórmula del SII.index, expected, actual

Transporte#

CódigoSe lanza cuandoDetails típicos
TRANSPORT_UNAVAILABLENo hay fetch en el runtime, o un adaptador de Node no pudo cargar node:https o node:fs.reason
TRANSPORT_FAILEDLa petición falló antes de que llegara una respuesta (DNS, conexión rechazada o reiniciada, una petición que no se puede armar).reason, operation, responseStarted
TRANSPORT_TLSFalló el handshake TLS o la verificación del certificado.reason (el código de OpenSSL o del SO), operation
REQUEST_TIMEOUTVenció el timeout de la llamada.operation, timeoutMs, reason
REQUEST_ABORTEDSe disparó el AbortSignal del llamador.operation

Cuando una falla de transporte ocurre después de que llegaron las cabeceras de la respuesta (mientras se leía el cuerpo), details.responseStarted es true: el SII sí respondió, al menos en parte.

Servicios web del SII#

CódigoSe lanza cuandoDetails típicos
SII_HTTP_ERROREl SII respondió con un estado HTTP que no es 2xx.httpStatus, operation, channel, url, body (extracto, tachado), retryAfterMs
SII_RESPONSE_INVALIDLa respuesta no se puede interpretar: no es el XML o JSON que devuelve el canal, o le falta el elemento o código esperado.operation, body
SII_SOAP_FAULTEl SII respondió con un fault SOAP.code, reason (tachado), operation
SII_SEED_FAILEDEl SII se negó a entregar una semilla.code, channel
SII_TOKEN_FAILEDEl SII se negó a entregar un token para una semilla firmada.code, channel
SII_TOKEN_INVALIDEl SII rechazó el token. El cliente lo renueva y repite la llamada una vez; esto sale solo si el token nuevo también se rechaza.operation, channel, httpStatus o status o code, attempts
SII_UPLOAD_REJECTEDEl SII rechazó un envío: un estado de DTEUpload distinto de recibido o duplicado, o más de 500 boletas en el canal REST.status (un número, o 'TOO_MANY'), errors, fileName, operation, message, trackIdElement
SII_QUERY_ERRORUna consulta de estado respondió un código negativo -1 a -14: falló el servicio de consulta, no tu sobre.operation, code, reason
WAIT_TIMEOUTwaitForUploadStatus agotó su presupuesto de tiempo con el estado aún pendiente.trackId, attempts, lastCode

Portal#

CódigoSe lanza cuandoDetails típicos
SII_PORTAL_LOGIN_FAILEDEl inicio de sesión no entregó sesión.operation, portalMessage
SII_PORTAL_CERT_NOT_ENABLEDEl certificado no está habilitado en el SII como método de ingreso.operation, portalMessage
SII_PORTAL_SESSION_LIMITEl SII informa demasiadas sesiones autenticadas para el RUT.operation
SII_PORTAL_SESSION_EXPIREDEl portal sigue pidiendo autenticación.operation, step
SII_PORTAL_BLOCKEDEl firewall del SII o un captcha bloqueó la petición.operation, step, httpStatus, portalMessage
SII_PORTAL_REJECTEDEl portal entendió la solicitud y la rechazó. details.rejection dice por qué.rejection, operation, más extras como portalMessage, file, httpStatus
SII_PORTAL_UNEXPECTED_PAGEEl portal respondió una página que no se puede interpretar.operation, step, portalMessage, body

Dependencias opcionales#

CódigoSe lanza cuandoDetails típicos
DEPENDENCY_UNAVAILABLEUna función de dte-sdk/pdf necesita pdf-lib o bwip-js y no está instalado.module, reason
PDF_RENDER_FAILEDLa biblioteca de PDF falló al dibujar una muestra impresa.reason, type, folio

Reintentos#

isRetryableError(error) es true para:

ErrorCondición
TRANSPORT_FAILED, REQUEST_TIMEOUTsiempre
SII_RESPONSE_INVALIDsiempre (una página ilegible suele ser una falla pasajera del servicio)
SII_QUERY_ERRORsiempre
SII_HTTP_ERRORhttpStatus 429, 405 o 5xx
SII_UPLOAD_REJECTEDstatus 9 ("sistema bloqueado")

Es false para todo lo demás, incluidos TRANSPORT_TLS (un almacén de confianza mal configurado no se arregla solo) y SII_TOKEN_INVALID (el cliente ya renueva el token una vez). El cliente del SII la usa como valor por defecto de retry.retryOn, con backoff exponencial y seis intentos. Dos cosas que recordar:

  • Un envío o un reclamo no se reintenta solo porque el error sea reintentable. Esas llamadas cambian estado en el SII y se reenvían únicamente mientras no haya llegado respuesta. SII_UPLOAD_REJECTED con estado 9 es "reintentable" según esta función, pero un envío que recibió esa respuesta nunca se reenvía automáticamente: lo decides tú. Ver la política de reintentos.
  • El portal tiene su propia regla, isRetryablePortalError de dte-sdk/portal: fallas de transporte, timeouts, HTTP 502, 503 y 504, y las fallas TLS intermitentes que el SII produce con un certificado cliente (EPROTO). Un límite de sesiones, un bloqueo o un rechazo nunca se repite, porque repetir los empeora. Su política, DEFAULT_PORTAL_RETRY_POLICY, es de 4 intentos a los 2, 4 y 8 segundos, sin jitter.

Rechazos del portal#

Un SII_PORTAL_REJECTED es el portal rechazando una solicitud por motivos de negocio: la empresa no está inscrita, se agotó el cupo, el respaldo está bloqueado. details.rejection es un código PortalRejection. portalRejectionMessage(rejection) y el mapa PORTAL_REJECTIONS, ambos de dte-sdk/portal, entregan la explicación completa en español, escrita para el operador, con qué hacer al respecto.

TypeScript
import { isDteError } from 'dte-sdk'
import { portalRejectionMessage, requestCaf, type PortalRejection } from 'dte-sdk/portal'
 
try {
  await requestCaf(portal, { type: 33, quantity: 50 })
} catch (error) {
  if (isDteError(error) && error.code === 'SII_PORTAL_REJECTED') {
    console.error(portalRejectionMessage(error.details.rejection as PortalRejection))
    console.error(error.details.portalMessage) // lo que dijo el portal, cuando dijo algo
  } else {
    throw error
  }
}

Los códigos, por área:

ÁrearejectionSignificado (breve)
AccesoinPersonRequiredEl representante legal debe completar la inscripción en persona en una oficina del SII.
companyNotAuthorizedLa empresa no está autorizada como emisor electrónico en este ambiente. queryAuthorizedIssuer lo lanza para un RUT que no figura en el registro público.
optionNotAuthorizedEl SII dice que la opción no está autorizada, sin indicar la causa; lo más frecuente es que la empresa aún no esté autorizada.
userWithoutPermissionEl RUT del certificado no tiene permisos en la empresa en este ambiente, o el SII dice que el usuario no está autorizado para solicitar timbraje ("No está autorizado para solicitar timbraje").
personWithPendingIssuesLa persona autenticada tiene situaciones pendientes con el SII.
activityVerificationPendingEl RUT no registra verificación de actividades para este tipo de documento.
notEnrolledLa empresa no está inscrita en la postulación a factura electrónica, así que no se puede descargar el set de pruebas.
Folios y CAFstampingBlockedEl SII no autoriza timbraje: hay folios suficientes sin usar.
typeNotEnabledEl SII no ofrece este tipo de documento para timbraje con este RUT.
quotaInsufficient, quotaExceeded, quotaCapReached, foliosShortEl SII autoriza menos folios de los pedidos, o la solicitud excede el máximo.
noAnnullableFoliosEl timbraje está limitado y no quedan folios anulables.
stampingUncertainEl SII volvió a mostrar el formulario de solicitud sin entregar folios ni decir por qué, así que no se sabe si autorizó el rango. La solicitud no se envía de nuevo: revisa los rangos que se pueden reobtener antes de pedir otra vez. requestCafInBatches lo informa como tal.
rangeAlreadyAuthorized, rangeAnnulledEl rango ya fue autorizado (se puede reobtener) o está anulado.
reobtainFormMissing, reobtainDownloadMissing, reobtainCafMissingEl SII no devolvió el formulario, la descarga o el CAF al reobtener un rango. Una página de ingreso en su lugar es SII_PORTAL_SESSION_EXPIRED.
CertificaciónadvanceRefused, declarationDeclinedEl portal no avanzó la postulación o no ofreció el formulario de declaración.
exchangeUploadRefusedEl portal de intercambio rechazó un archivo de respuesta (details.file).
samplesReviewRefused, sampleUploadRefusedEl portal de muestras impresas no creó la revisión, o rechazó un PDF con un estado 4xx.
receiptsNotEnrolled, receiptsTrackIdRefused, receiptsComplianceRefusedLa postulación de boletas rechazó: sin inscripción, el track id del set o la declaración de cumplimiento.
Respaldo MIPYMEbackupCaptchaEl SII activó un captcha. Intentar más tarde, nunca en un loop.
backupIndeterminateLa página dio varios mensajes y ningún veredicto único. Intentar más tarde.
backupNoDataEl SII informa que no hay información para este RUT. Un veredicto definitivo.
backupRefused, backupNoCompanyEl portal rechazó, o respondió la página de selección de empresa sin mensaje.
backupDayOverLimit, backupDayUnknownTypesUn solo día supera los 20 documentos por descarga y no se puede dividir. No se descargó nada.
RegistropurchaseChangeNotConfirmedEl SII no confirmó un cambio en el registro de compras, pero pudo haberse aplicado: relee el documento antes de reintentar.
Verificación de actividadesactivityVerificationRefusedEl SII respondió la verificación de actividades con un código de error; sus palabras van en details.portalMessage cuando dijo algo.

Ver Portal y Registro para las funciones que hay detrás.

Códigos de estado#

El SII informa los resultados con códigos cortos. El SDK los devuelve como dato (no son excepciones), los clasifica y entrega su glosa en español. Las glosas están en español porque son el vocabulario propio del SII.

TypeScript
import {
  classifyDocumentStatus,
  classifyUploadStatus,
  documentStatusMessage,
  isRetryableStatus,
  isTokenErrorStatus,
  uploadStatusMessage,
} from 'dte-sdk'
 
classifyUploadStatus('EPR') // 'accepted'
classifyUploadStatus('RCT') // 'rejected'
classifyUploadStatus('-11') // 'queryError': reintentar
classifyUploadStatus('RLV') // 'rejected' en SOAP…
classifyUploadStatus('RLV', 'rest') // …y 'accepted' en la API REST de boletas
classifyUploadStatus('XYZ') // 'unknown'
classifyDocumentStatus('FAU') // 'notReceived'
 
uploadStatusMessage('EPR') // 'Envío procesado'
documentStatusMessage('FAU') // 'DTE no recibido por el SII'
isRetryableStatus('-11') // true
isTokenErrorStatus('-3') // true: renueva el token y prueba una vez más

Estados de envío#

El ESTADO de QueryEstUp (o el estado REST) de un sobre o un libro. classifyUploadStatus(code, channel = 'soap') devuelve una de estas clases; uploadStatusMessage(code, channel) la glosa, o Estado desconocido: <code>.

ClaseCódigos
acceptedEPR (envío procesado), LOK (envío de libro aceptado)
acceptedWithObjectionsRPR (aceptado con reparos)
pendingREC (recibido, esperando validación), SOK (schema validado, validando firma), FOK (firma validada, procesando), PRD (en proceso, validando carátula), CRT (carátula validada, finalizando), DNK (en proceso de revisión), PDR (en proceso, validando), LSO (schema de libro correcto, procesando contenido), 0 (enviado, pendiente de validación)
rejectedRPT (rechazado por schema), RFR (error en firma), VOF (error interno del SII), RCT (error en carátula), RCH (rechazado), RCO (envío rechazado), RSC (error en schema), RLV (error en documento; éxito en REST), LNC (tipo de envío de libro no corresponde), LRH (libro rechazado con historial)
queryError-1 a -14: fallas del servicio de consulta, no de tu archivo. -3 y -13 significan token rechazado.
unknownCualquier otro.

isRetryableStatus(code) es true para la clase queryError. isTokenErrorStatus(code) es true para -3, -13, 001, 002 y 003: el cliente renueva el token una vez cuando ve uno.

Estados de recepción#

El STATUS de la respuesta RECEPCIONDTE que entrega DTEUpload cuando recibe (o rechaza) un archivo. RECEPTION_STATUS es el catálogo, classifyReceptionStatus(code) la clase y receptionStatusMessage(code) la glosa. SII_UPLOAD_REJECTED.details.status es este código como número.

STATUSClaseSignificado
0receivedEnvío recibido, TrackID asignado.
1rejectedEl remitente no tiene permiso para enviar por esta empresa.
2rejectedError en el tamaño del archivo (muy grande o muy chico).
3rejectedArchivo cortado o incompleto.
5notAuthenticatedNo autenticado: token ausente o vencido. El cliente renueva el token y envía de nuevo una vez.
6rejectedEmpresa no autorizada a enviar archivos.
7schemaInvalidEsquema inválido o archivo ya enviado (ver DETAIL). El cliente los distingue: los errores de esquema o de charset (CHR-…, SCH-…, cvc-…) son un rechazo; si no, con un TrackID en la respuesta, es un duplicado.
8rejectedError en la firma del documento.
9rejectedSistema bloqueado, reintentar más tarde. El único que se resuelve solo.
99alreadyUploadedArchivo ya fue enviado anteriormente. Un duplicado cuando la respuesta nombra el TrackID.

Estados de documento#

El ESTADO de QueryEstDte (o el codigo REST) de un documento. classifyDocumentStatus(code) y documentStatusMessage(code); cualquier código negativo es queryError, y cualquier otro no listado es unknown.

ClaseCódigoGlosa
receivedDOKDocumento recibido por el SII, datos coinciden
receivedWithMismatchDNKDocumento recibido por el SII, datos no coinciden
notReceivedFAUDTE no recibido por el SII
notAuthorizedFNADTE no autorizado
EMPEmpresa no autorizada a emitir DTE
modifiedTMD, TMCExiste nota de débito o de crédito que modifica textos
MMD, MMCExiste nota de débito o de crédito que modifica montos
cancelledAND, ANCExiste nota de débito o de crédito que anula el documento
FANFolio anulado

Códigos de reclamo y de cedibilidad#

El registro responde con un número codResp. claimResponseMessage(code) entrega la glosa (Código de respuesta desconocido: <code> para un código no listado), y CLAIM_RESPONSE_CODES es el catálogo.

codRespGlosa
0Acción completada OK
1RUT del emisor erróneo
2Folio erróneo
3El tipo de documento no corresponde
4Acción inválida
5DTE ya reclamado
6No se puede otorgar recibo de mercaderías a un DTE reclamado
7Evento registrado previamente
8Han pasado más de 8 días desde la recepción del documento
9No existen registros para los parámetros indicados
10DTE no recibido en el SII desde el 14-01-2017
11No se puede reclamar un DTE aceptado previamente
12No se puede aceptar un DTE rechazado previamente
13No se puede reclamar un DTE con recibo de mercaderías
14Solo la empresa receptora o emisora puede consultar
15Lista de eventos del documento
16El documento no tiene eventos registrados
17Solo la empresa receptora puede registrar eventos
18Documento no recibido en el SII
19Reclamo por mercaderías ya realizado
27No se puede registrar un evento de un DTE pagado al contado o gratuito
-1Error interno del SII, reintentar

queryTransferable responde con los códigos 20 a 25. transferabilityMessage(code) entrega la glosa, y TRANSFERABILITY_CODES el catálogo, con lo que implica cada uno:

codResptransferableGlosa
20falseTipo de documento no cedible
21falseNo cedible: anulado por nota de crédito dentro de los 8 días
22nullSin registro de reclamo ni de recibo de mercaderías
23trueCedible, sin reclamos registrados
24falseNo cedible: reclamado por el receptor
25trueCedible: transcurridos 8 días sin reclamo, se presume recibido

Los eventos que informa listClaimEvents (CLAIM_EVENT_CODES): ACD (acepta contenido), RCD (reclamo al contenido), ERM (otorga recibo de mercaderías o servicios), RFP (reclamo por falta parcial), RFT (reclamo por falta total), NCA (nota de crédito de anulación), ENC (otra nota de crédito) y PAG (DTE pagado al contado, que registra el propio SII).

El código 27 es el registro rechazando un evento sobre un documento pagado al contado o gratuito: producción lo respondió el 11 de noviembre de 2026 a la aceptación de una factura cuyos eventos listaban solo PAG. receiverAnswer lee un documento así como paidInCash, así que no hay nada que enviar (revisa receiverAnswer). Antes de la 0.8.0 el catálogo no lo conocía, y claimResponseMessage(27) daba Código de respuesta desconocido: 27.

Próximos pasos#

  • Servicios web del SII muestra de dónde vienen estos errores y estados, y cómo funcionan los reintentos y la renovación de token.
  • Portal explica la sesión, los límites y los rechazos del portal.
  • Seguridad dice qué mantener fuera de tus logs.