rwf2/Rocket · critical · io::Error
error reading TLS file `{source}`: {e}
Error message
error reading TLS file `{source}`: {e} What it means
Configuration/startup error from Rocket's TLS setup (core/lib/src/tls/config.rs): while converting the configured certs/keys value into a reader, opening the configured file path failed; the io error is re-wrapped with a message naming the figment Source::File path ('error reading TLS file `path`: e'). This surfaces during server ignition when TLS is configured via Rocket.toml ([tls] certs/key/muts), and the underlying io::Error kind (NotFound, PermissionDenied, ...) is preserved.
Source
Thrown at core/lib/src/tls/config.rs:614
];
/// Used as the `serde` default for `ciphers`.
fn default_set() -> IndexSet<Self> {
Self::DEFAULT_SET.iter().copied().collect()
}
}
pub(crate) fn to_reader(
value: &Either<RelativePathBuf, Vec<u8>>
) -> io::Result<Box<dyn io::BufRead + Sync + Send>> {
match value {
Either::Left(path) => {
let path = path.relative();
let file = std::fs::File::open(&path)
.map_err(move |e| {
let source = figment::Source::File(path);
let msg = format!("error reading TLS file `{source}`: {e}");
io::Error::new(e.kind(), msg)
})?;
Ok(Box::new(io::BufReader::new(file)))
}
Either::Right(vec) => Ok(Box::new(io::Cursor::new(vec.clone()))),
}
}
#[cfg(test)]
mod tests {
use super::*;
use figment::{Figment, providers::{Toml, Format}};
#[test]
fn test_tls_config_from_file() {
use crate::tls::{TlsConfig, CipherSuite};
use pretty_assertions::assert_eq;
View on GitHub (pinned to 3a54d079ae)
Solutions
- Run the binary from the directory the TLS paths are relative to, or use absolute paths in Rocket.toml
- Verify existence and permission as the service user: sudo -u app cat /etc/app/certs.pem
- In containers, double-check the mount target matches the configured path exactly
- If certs rotate, ensure the new file replaces the path atomically and restart the service
Example fix
# before # Rocket.toml [default.tls] certs = "certs.pem" # run from another dir → NotFound key = "key.pem" # after [default.tls] certs = "/etc/myapp/certs.pem" key = "/etc/myapp/key.pem" # $ sudo -u myapp cat /etc/myapp/key.pem # must succeed
Defensive patterns
Strategy: validation
Validate before calling
// at startup, verify TLS files exist and are readable before ignite
fn tls_files_ok(certs: &str, key: &str) -> io::Result<()> {
for p in [certs, key] {
let path = std::path::Path::new(p);
if !path.is_absolute() { /* relative to CWD: verify CWD matches deployment */ }
std::fs::File::open(path)?; // fails with NotFound/PermissionDenied early
}
Ok(())
} Try / catch
match rocket::custom(figment).launch().await {
Err(e) if e.to_string().contains("error reading TLS file") => {
eprintln!("TLS config broken — check cert/key paths and permissions: {e}");
std::process::exit(2);
}
other => { let _ = other?; }
} Prevention
- Use absolute TLS paths in production configs
- Add a pre-launch readiness check (or entrypoint script) that cats both files as the service user
- Pin cert file names across renewals (atomic replace, same path) so config never goes stale
When it happens
Trigger: Rocket.toml has [default.tls] certs = "certs.pem" key = "key.pem", and the relative path doesn't resolve from the binary's working directory at launch, the file is missing, or the process lacks read permission. Also triggers when paths are correct in CI but wrong in the container, or when key files are mounted with root-only permissions.
Common situations: Running the binary from a different CWD than during development (relative TLS paths silently break); Docker volumes mounting certs at another path; cert-manager renewal renaming files; systemd services with ProtectHome= making paths unreadable.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
AI-assisted analysis of rwf2/Rocket@3a54d079ae (2026-08-16).
Data as JSON: /api/errors/d7c8f353fba43caf.
Report an issue: GitHub.