rathole-org/rathole · error
Missing `pkcs12` or `pkcs12_password`
Error message
Missing `pkcs12` or `pkcs12_password`
What it means
The TLS transport is enabled and a `[transport.tls]` section exists, but on the server side either `pkcs12` (the certificate file) or `pkcs12_password` is missing. The validator requires BOTH fields via `pkcs12.as_ref().and(pkcs12_password.as_ref())` before the server can load its identity.
Solutions
- Add both `pkcs12 = "path/to/cert.p12"` and `pkcs12_password = "..."` under `[transport.tls]` on the server
- If you only have a PEM cert/key, convert it: `openssl pkcs12 -export -out cert.p12 -inkey key.pem -in cert.pem`
- Confirm the config is intended for a server — clients don't need pkcs12; check `is_server` matches your role section
- Verify the keys are inside `[transport.tls]`, not a sibling table
Example fix
# before [transport.tls] pkcs12 = "server.p12" # after [transport.tls] pkcs12 = "server.p12" pkcs12_password = "changeit"
Defensive patterns
Strategy: validation
Validate before calling
let raw: toml::Value = toml::from_str(&cfg)?;
let tls = &raw["transport"]["tls"];
let is_server = raw.get("server").is_some();
if is_server && (tls["pkcs12"].is_none() || tls["pkcs12_password"].is_none()) {
return Err("server TLS config needs both pkcs12 and pkcs12_password".into());
} Prevention
- Store pkcs12 path and password together (e.g. via env/secret manager) and set both keys
- Convert certs to PKCS#12 with openssl before writing the config
- Confirm which role (server/client) a config file serves before reusing it
When it happens
Trigger: Running rathole in server mode with `transport.type = "tls"` where `[transport.tls]` defines only one of `pkcs12` or `pkcs12_password`, or neither; also when the keys are placed in the wrong table so they don't deserialize into `TlsConfig`.
Common situations: Server operators generate a certificate but forget the export password; they move the p12 file without updating the config; client-side configs mistakenly include server fields or omit them while the same config is reused for a server.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- Missing TLS configuration
- Neither of `[server]` or `[client]` is defined
- Unknown proxy scheme
- Missing tls config
- Missing tls config
AI-assisted analysis of rathole-org/rathole@a292f7ed54 (2026-09-07).
Data as JSON: /api/errors/36856a32107ef004.
Report an issue: GitHub.
Appendix: source
Thrown at src/config.rs:317
.as_ref()
.map_or(Ok(()), |u| match u.scheme() {
"socks5" => Ok(()),
"http" => Ok(()),
_ => Err(anyhow!(format!("Unknown proxy scheme: {}", u.scheme()))),
})?;
match config.transport_type {
TransportType::Tcp => Ok(()),
TransportType::Tls => {
let tls_config = config
.tls
.as_ref()
.ok_or_else(|| anyhow!("Missing TLS configuration"))?;
if is_server {
tls_config
.pkcs12
.as_ref()
.and(tls_config.pkcs12_password.as_ref())
.ok_or_else(|| anyhow!("Missing `pkcs12` or `pkcs12_password`"))?;
}
Ok(())
}
TransportType::Noise => {
// The check is done in transport
Ok(())
}
TransportType::Websocket => Ok(()),
}
}
pub async fn from_file(path: &Path) -> Result<Config> {
let s: String = fs::read_to_string(path)
.await
.with_context(|| format!("Failed to read the config {:?}", path))?;
Config::from_str(&s).with_context(|| {
"Configuration is invalid. Please refer to the configuration specification."
})View on GitHub (pinned to a292f7ed54)