vllm-project/vllm · error
--ssl-certfile is required to enable TLS; --ssl-keyfile/--ss
Error message
--ssl-certfile is required to enable TLS; --ssl-keyfile/--ssl-ca-certs/--ssl-cert-reqs/--ssl-ciphers cannot be used without it
What it means
Thrown by TlsConfig::validate() when any TLS option (--ssl-keyfile, --ssl-ca-certs, --ssl-cert-reqs, --ssl-ciphers) is set but --ssl-certfile is not. The Rust frontend mirrors Python uvicorn's ssl_* arguments and treats the server certificate as the switch that enables TLS; structural validation runs at startup, before the OpenSSL context is built.
Source
Thrown at rust/src/server/src/config.rs:135
/// (combined PEM).
pub key_file: Option<String>,
/// PEM CA bundle used to verify client certificates (mTLS). Required when
/// `cert_reqs` is non-zero.
pub ca_certs: Option<String>,
/// Client-certificate requirement, mirroring Python's `ssl.CERT_*`:
/// 0 = none, 1 = optional, 2 = required.
pub cert_reqs: i32,
/// OpenSSL cipher string for TLS 1.2 and below, mirroring Python's
/// `ssl.set_ciphers`. `None` keeps the forward-secret AEAD default.
pub ciphers: Option<String>,
}
impl TlsConfig {
/// Structurally validate the TLS arguments; the cert/key material is parsed
/// later, when the OpenSSL context is built.
pub fn validate(&self) -> Result<()> {
if self.cert_file.is_none() {
bail!(
"--ssl-certfile is required to enable TLS; \
--ssl-keyfile/--ssl-ca-certs/--ssl-cert-reqs/--ssl-ciphers \
cannot be used without it"
);
}
if !matches!(self.cert_reqs, 0..=2) {
bail!(
"--ssl-cert-reqs must be 0 (none), 1 (optional), or 2 (required), got {}",
self.cert_reqs
);
}
if self.cert_reqs != 0 && self.ca_certs.is_none() {
bail!(
"--ssl-ca-certs is required when --ssl-cert-reqs is {} \
(client certificate verification)",
self.cert_reqs
);
}View on GitHub (pinned to c794754062)
Solutions
- Add --ssl-certfile pointing to your PEM certificate chain: --ssl-certfile server.pem --ssl-keyfile server.key.
- If the PEM contains both cert and key, --ssl-certfile alone is sufficient per the TlsConfig docs.
- If you did not intend to enable TLS, remove all --ssl-* flags (including --ssl-ciphers and --ssl-cert-reqs defaults set by your launcher).
- Verify flag ordering in your unit/systemd file — a missing value can silently consume the next flag.
Example fix
# before vllm serve model --ssl-keyfile server.key --ssl-ca-certs ca.pem # after vllm serve model --ssl-certfile server.pem --ssl-keyfile server.key --ssl-ca-certs ca.pem
Defensive patterns
Strategy: validation
Validate before calling
fn tls_config_complete(cert: &Option<PathBuf>, others_set: bool) -> bool {
!others_set || cert.is_some()
} Type guard
fn tls_is_structurally_valid(tls: &Option<TlsConfig>) -> bool {
match tls {
None => true,
Some(t) => t.cert_file.is_some(),
}
} Try / catch
match config.tls.as_ref().map(|t| t.validate()) {
Some(Err(e)) => eprintln!("TLS config rejected: {e}"),
_ => {}
} Prevention
- Treat --ssl-certfile as the TLS on-switch: set it first, then other --ssl-* flags.
- Write TLS flags as one block in the unit file so they move together.
- Run a preflight that calls Config::validate() before exec'ing the server.
When it happens
Trigger: Configuring e.g. --ssl-keyfile server.key --ssl-cert-reqs 2 without also passing --ssl-certfile server.pem. Also triggered by setting only --ssl-ciphers or only --ssl-ca-certs. Any TlsConfig with cert_file == None fails validate() unconditionally, even if all other fields are defaults.
Common situations: Migrating a deployment where the cert/key live in a combined PEM and only the key flag was carried over; CI pipelines that template TLS flags conditionally; combining-peer-cert (mTLS) setup where --ssl-ca-certs was added first.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- --ssl-cert-reqs must be 0 (none), 1 (optional), or 2 (requir
- --ssl-ca-certs is required when --ssl-cert-reqs is {} (clien
- invalid --allowed-methods value {method:?}: {e}
- invalid --allowed-headers value {header:?}: {e}
- max_logprobs must be non-negative or -1, got {}
AI-assisted analysis of vllm-project/vllm@c794754062 (2026-08-14).
Data as JSON: /api/errors/4a605383c6e9e721.
Report an issue: GitHub.