> ## Documentation Index
> Fetch the complete documentation index at: https://x-preview-mintlify-d8d2882f.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Solución de problemas

> Diagnostica problemas comunes de cifrado en X Chat, incluidos errores del Chat XDK, recuperación de copia de seguridad segura de claves, fallos de descifrado y construcción de payloads de envío firmados.

Esta página cubre problemas que son **específicos del cifrado de X Chat y del Chat XDK**—claves, copia de seguridad segura de claves, descifrar/verificar, y construcción de payloads de envío cifrados.

Para webhooks, OAuth, códigos de estado HTTP y límites de tasa, usa la documentación general de la [X API](/es/x-api/introduction) y de [autenticación](/es/fundamentals/authentication/overview).

***

## Claves y copia de seguridad segura de claves

### Falla el unlock (código de acceso inválido)

* Confirma que el código de acceso coincide con el usado con `setup`
* Espera entre intentos; los realms limitan por tasa los intentos erróneos y pueden bloquear la recuperación tras demasiados fallos

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    try:
        chat.unlock(passcode)
    except ValueError as e:
        print(e)  # may mention InvalidPin or guesses remaining
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    try {
      await chat.unlock(passcode);
    } catch (e) {
      console.error((e as Error).message);
    }
    ```
  </Tab>

  <Tab title="Rust">
    ```rust theme={null}
    chat.unlock(passcode_bytes).await?;
    ```
  </Tab>

  <Tab title="Go">
    ```go theme={null}
    if err := chat.Unlock(passcode, juiceboxConfigJSON); err != nil {
        log.Println(err)
    }
    ```
  </Tab>

  <Tab title="C#">
    ```csharp theme={null}
    try { chat.Unlock(passcode, juiceboxConfigJson); }
    catch (Exception e) { Console.WriteLine(e.Message); }
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    try { chat.unlock(passcode, juiceboxConfigJson); }
    catch (Exception e) { System.out.println(e.getMessage()); }
    ```
  </Tab>
</Tabs>

### Cifrar o descifrar falla porque las claves o la identidad no están configuradas

Carga primero las claves privadas, luego configura la **identidad de sesión**—tu user id más el `public_key_version` de tu registro en X. Los métodos `encrypt_*` y `prepare_*` firman con ella; llamarlos sin identidad de sesión (y sin una anulación explícita por llamada) es un error.

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    chat.unlock(passcode)  # or: chat.import_keys(blob)
    chat.set_identity(my_user_id, signing_key_version)
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    await chat.unlock(passcode);
    chat.setIdentity(myUserId, signingKeyVersion);
    ```
  </Tab>

  <Tab title="Rust">
    ```rust theme={null}
    chat.import_keys(&blob)?;
    chat.set_identity(&my_user_id, &signing_key_version);
    ```
  </Tab>

  <Tab title="Go">
    ```go theme={null}
    blob, _ := chatxdk.Base64ToBytes(privateKeysB64)
    _ = chat.ImportKeys(blob)
    _ = chat.SetIdentity(myUserID, signingKeyVersion)
    ```
  </Tab>

  <Tab title="C#">
    ```csharp theme={null}
    chat.ImportKeys(blobBytes);
    chat.SetIdentity(myUserId, signingKeyVersion);
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    chat.importKeys(blobBytes);
    chat.setIdentity(myUserId, signingKeyVersion);
    ```
  </Tab>
</Tabs>

### Falta la clave de conversación para un mensaje

Un error como `Message encrypted with key version '…' but no matching key found` significa que no tienes la clave en **bruto** para el `conversation_key_version` de ese mensaje.

1. Descifra el material de clave desde `conversation_key_change_event` (eventos en vivo) o `meta.conversation_key_events` (historial) con `extract_conversation_keys`, **o** incluye esos blobs en `decrypt_events`—con `set_cache_keys(true)` habilitado, `decrypt_events` también retiene la última clave verificada de cada conversación para que las llamadas posteriores `decrypt_event` y `encrypt_*` puedan omitirla
2. Confirma que se añadieron claves de conversación para esa versión y que sigues siendo participante (consulta [Primeros pasos](/es/xchat/getting-started#4-set-up-conversation-keys))

### El par no tiene claves públicas

Es posible que no haya terminado el onboarding. Después de que se registre, carga `public_key`, `signing_public_key`, `identity_public_key_signature` y `public_key_version` desde **API reference → Encryption keys**.

***

## Descifrado y firmas

### Falla el descifrado

* Clave de conversación en **bruto** obsoleta o incorrecta, o versión de clave incorrecta
* Cadena `encoded_event` incompleta
* El tipo de evento no es un mensaje cifrado que puedas tratar como contenido descifrable

### La firma no se verifica

La verificación es **fail-closed por defecto** (`reject_unverified = true`): el SDK ya rechaza eventos firmados no verificados, así que un fallo aquí significa que las entradas de verificación son incorrectas, no que necesites activar la comprobación. Causas comunes:

* Entrada de clave de firma faltante o incompleta para el **remitente** (todos los campos requeridos por el Chat XDK—consulta la referencia del [Chat XDK](/es/xchat/xchat-xdk))
* No se pasaron claves de firma en la llamada y no hay ninguna almacenada mediante `set_signing_keys`
* El remitente rotó versiones—vuelve a obtener sus claves públicas
* Una versión de clave por debajo del mínimo aceptado nunca se verifica

El setter `set_reject_unverified` existe para **desactivar** este comportamiento predeterminado (`false`, no recomendado). Si lo desactivaste antes, restaura el predeterminado fail-closed:

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    chat.set_reject_unverified(True)
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    chat.setRejectUnverified(true);
    ```
  </Tab>

  <Tab title="Rust">
    ```rust theme={null}
    chat.set_reject_unverified(true);
    ```
  </Tab>

  <Tab title="Go">
    ```go theme={null}
    chat.SetRejectUnverified(true)
    ```
  </Tab>

  <Tab title="C#">
    ```csharp theme={null}
    chat.SetRejectUnverified(true);
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    chat.setRejectUnverified(true);
    ```
  </Tab>
</Tabs>

### Una respuesta lleva `reply_preview_validation: "Invalid"`

Las respuestas descifradas pueden llevar `reply_preview_validation` (`"Valid"` / `"Invalid"`; JavaScript usa `'valid'` / `'invalid'`). `Invalid` significa que la vista previa citada dentro del mensaje no coincide con el evento original firmado que incrusta—trata la cita como no confiable y renderiza el contenido citado solo desde el original validado. El mensaje en sí se verifica por separado y sigue siendo auténtico; nada se lanza por una vista previa inválida.

### Los eventos antiguos fallan permanentemente la verificación

Errores como `signature missing or no matching signing key` o una discrepancia ECDSA en eventos **antiguos** son permanentes. Las firmas son inmutables y se verifican reconstruyendo el payload firmado a partir del propio evento, así que un evento que fue firmado sobre bytes diferentes (o nunca firmado) fallará en cada carga futura—ningún reintento, refresco de claves ni llamada a la API puede sanarlo. Trata estos eventos como tombstones, no como errores reintentables. Rotar la clave de conversación inicia un historial limpio y verificable a partir de ese punto hacia adelante; los nuevos mensajes no se ven afectados.

***

## Construyendo el payload de envío

Estos errores son específicos del cifrado de X Chat (no son errores HTTP generales):

| Problema                          | Solución                                                                                                                                                                                                                                                 |
| :-------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Bytes de clave incorrectos        | Pasa los bytes de la clave de conversación en **bruto** al Chat XDK, no la cadena de clave cifrada de la API                                                                                                                                             |
| Nombres de campo JSON incorrectos | Mapea `encrypted_content` → `encoded_message_create_event` y `encoded_event_signature` → `encoded_message_event_signature`                                                                                                                               |
| ID de mensaje incorrecto          | Envía el `message_id` del payload devuelto—el SDK lo genera y lo incrusta en el evento firmado, así que cualquier otro valor falla. En los reintentos, reutiliza el mismo payload cifrado para que el ID nunca se genere dos veces                       |
| Discrepancia de versión           | Alinea `conversation_key_version` con la clave que uses; alinea la versión de la clave de firma pasada a `set_identity` con tu registro de public-key                                                                                                    |
| Forma del ID en la ruta           | Las rutas URL todavía necesitan el ID de conversación con guiones (`:` → `-`), pero para firmar el SDK acepta cualquier forma: `A:B`, `A-B` (en cualquier orden), o el user id del destinatario a secas—todo se canonicaliza a los mismos bytes firmados |

### La API devuelve 400 para una llamada que cambia el estado

Cada llamada de chat que cambia el estado—añadir o rotar claves de conversación, crear un grupo, añadir miembros—requiere **`action_signatures`** en el cuerpo de la solicitud, validadas en el límite de la API. Una entrada faltante o mal formada (cada una necesita `message_id`, `encoded_message_event_detail` y una `message_event_signature` con `signature`, `public_key_version` y `signature_version`) devuelve una respuesta problem-details HTTP 400 de inmediato. Usa los métodos prepare del SDK (`prepare_conversation_key_change`, `prepare_group_create`, `prepare_group_members_change`) y envía **todas** las firmas devueltas—group create y member adds devuelven dos.

***

## Cifrado y descifrado de multimedia

* Usa la **misma** clave de conversación (y versión) que el mensaje que hace referencia al adjunto
* Trata las respuestas de descarga como **texto cifrado** hasta ejecutar `decrypt_stream`
* Infere el tipo MIME **después** de descifrar; el `Content-Type` de descarga a menudo no es el tipo real de la imagen

Detalles: [Multimedia](/es/xchat/media).

***

## Depuración segura

Al investigar fallos de criptografía:

* Registra en logs los IDs de conversación, los IDs de evento y las **versiones** de claves únicamente
* **No** registres en logs texto plano, códigos de acceso, claves privadas ni blobs de clave completos
* Confirma que la versión de la clave de firma pasada a `set_identity` coincide con el `public_key_version` de tu registro de public-key
* Para historial incompleto, pagina **todas** las páginas de eventos para no saltar los metadatos de key-change antes de descifrar
