Files
mfahampshire 7c890ea0c5 TS SDK docs (#6840)
* First sweep packages + some minor tweaking

* Second sweep

* Regenerate lockfile + package.json mods

* Regenerate lockfile again

* Fix CI

* Fix CI again

* All building properly

* unblock

* Tweak examples

* Comments + readme + fix rotten unit test

* First pass docs

* Big pass

* Massive pass on new docs

* Update integrations.md w mobile

* Partial overhaul review

* new playground + big pass

* new fix lychee err

* IPR notice tweak
2026-06-09 13:31:08 +00:00

85 lines
3.6 KiB
Plaintext

---
title: "Mixnet Module Troubleshooting"
description: "Solutions for common Nym Rust SDK issues: client disconnect errors, empty SURB messages, verbose logging, and database lock problems."
schemaType: "FAQPage"
section: "Developers"
lastUpdated: "2026-03-15"
---
# Troubleshooting
import { Callout } from 'nextra/components';
Common issues and how to resolve them.
## Always disconnect your client
You should always **manually disconnect your client** with `client.disconnect().await`. The client writes to a local DB and manages SURB storage, so it needs to shut down gracefully. Failing to do this can lead to the errors described below.
## Waiting for non-empty messages
When listening for a response, you may receive empty messages. These are SURB replenishment requests: the remote side asking for more reply SURBs. Filter them out:
```rust
let mut message = None;
while let Some(new_message) = client.wait_for_messages().await {
if !new_message.is_empty() {
message = new_message.into_iter().next();
break;
}
}
```
<Callout type="info">
Prefer `client.next().await` (from the `futures::StreamExt` trait, not the Nym Stream module) over `client.wait_for_messages().await`; it returns one message at a time which is easier to work with. You'll need `use futures::StreamExt;` in scope.
</Callout>
## Verbose `task client is being dropped` logging
### On client shutdown (expected)
When calling `client.disconnect().await`, the client logs that its background tasks are shutting down. This is normal and expected.
Control log verbosity with `RUST_LOG`:
```sh
RUST_LOG=warn cargo run --example simple
```
### Not on client shutdown (unexpected)
If you see these messages unexpectedly, you may be killing the client process too early. See the next section.
## Accidentally killing your client process too early
If you see errors like `Polling shutdown failed: channel closed` or panics about `action control task has died`, your client is being dropped before it finishes sending.
`send_plain_message()` is async, but **it only blocks until the message is placed in the client's internal queue**, not until it's actually sent into the Mixnet. After queuing, the client still needs to route-encrypt the message and interleave it with cover traffic.
Make sure the program stays alive long enough. In practice this means awaiting a response or calling `sleep` before disconnecting:
```rust
// Send a message
client.send_plain_message(recipient, "hello").await.unwrap();
// Wait for the reply (keeps the client alive)
if let Some(received) = client.wait_for_messages().await {
for r in received {
println!("Received: {}", String::from_utf8_lossy(&r.message));
}
}
// Always disconnect gracefully
client.disconnect().await;
```
## Lots of `duplicate fragment received` messages
`WARN` level logs about duplicate fragments are caused by Mixnet-level packet retransmission: the original and the retransmitted copy both arrive. This is not a bug in your client logic.
## Android: mixnet bootstrap fails with a certificate `Revoked` / OCSP error
When you compile the SDK for Android (via `uniffi` + `cargo-ndk`), the client can fail to bootstrap the mixnet with a hard `Revoked` or "Certificate does not specify OCSP responder" error on certain Validator endpoints. The cause is `rustls-platform-verifier` routing certificate validation through Java's `CertPathValidator`, which enforces an OCSP check the endpoint does not satisfy. iOS and the desktop targets are unaffected; they tolerate or skip the check.
Configure the client to use preconfigured TLS roots with `webpki_roots::TLS_SERVER_ROOTS` instead of the platform verifier to get around it.