aaif-goose/goose · error
Failed to parse CA certificate bundle: {}
Error message
Failed to parse CA certificate bundle: {} What it means
After reading the CA bundle, load_ca_certificates calls Certificate::from_pem_bundle on its bytes. If the file is valid text but not a PEM bundle (no BEGIN/END CERTIFICATE blocks, Base64 corrupted, or a lone private key), parsing fails with 'Failed to parse CA certificate bundle: {err}'. The read succeeded; the content is not a certificate bundle.
Source
Thrown at crates/goose-providers/src/api_client.rs:126
|e| anyhow::anyhow!("Failed to create identity from cert and key: {}", e),
)?
};
Ok(Some(identity))
} else {
Ok(None)
}
}
#[cfg(any(feature = "rustls-tls", feature = "native-tls"))]
fn load_ca_certificates(&self) -> Result<Vec<Certificate>> {
match &self.ca_cert_path {
Some(ca_path) => {
let ca_pem = read_to_string(ca_path)
.map_err(|e| anyhow::anyhow!("Failed to read CA certificate: {}", e))?;
let certs = Certificate::from_pem_bundle(ca_pem.as_bytes())
.map_err(|e| anyhow::anyhow!("Failed to parse CA certificate bundle: {}", e))?;
Ok(certs)
}
None => Ok(Vec::new()),
}
}
}
impl Default for TlsConfig {
fn default() -> Self {
Self::new()
}
}
/// Convert a PEM private key from any format (PKCS#1, SEC1, PKCS#8) to PKCS#8 PEM.
///
/// `reqwest::Identity::from_pkcs8_pem` (native-tls) only accepts PKCS#8
/// (`-----BEGIN PRIVATE KEY-----`), but private keys in the wild come in three formats:View on GitHub (pinned to 3810898a74)
Solutions
- Inspect the file: it must contain one or more -----BEGIN CERTIFICATE----- ... -----END CERTIFICATE----- blocks
- Re-download the CA properly: curl -fsSL -o ca.pem https://proxy.example/ca.pem
- Convert DER to PEM: openssl x509 -inform der -in ca.crt -out ca.pem
- Ensure exactly one newline between concatenated PEM blocks
Example fix
# before ca_cert_path: /etc/goose/tls/ca.pem # actually DER bytes or an HTML error page # after (shell) $ file /etc/goose/tls/ca.pem # expect: PEM certificate $ openssl x509 -inform der -in ca.der -out /etc/goose/tls/ca.pem $ openssl verify -CAfile /etc/goose/tls/ca.pem server-cert.pem
Defensive patterns
Strategy: validation
Validate before calling
let pem = std::fs::read_to_string(&ca_cert_path)?;
let blocks = pem.matches("-----BEGIN CERTIFICATE-----").count();
anyhow::ensure!(blocks > 0, "file contains no PEM certificate blocks"); Type guard
fn is_pem_certificate_bundle(path: &std::path::Path) -> bool {
std::fs::read_to_string(path)
.map(|s| s.contains("-----BEGIN CERTIFICATE-----"))
.unwrap_or(false)
} Prevention
- Sanity-check downloads: curl -fsSL and file ca.pem before trusting it
- Separate newlines between concatenated PEM blocks
- Validate the bundle against a known server: openssl verify -CAfile ca.pem server.pem
- Prefer PEM from the CA owner over re-encoding DER yourself when possible
When it happens
Trigger: ca_cert_path points at a file that is not PEM: a DER binary renamed .pem, a concatenated chain with a broken Base64 body, a chain with Windows line endings or stray headers that break armor detection, or a JSON/HTML error page saved by mistake (e.g. a failed download).
Common situations: Downloading a CA via curl without following redirects and saving an error page; cert managers writing DER despite the extension; hand-concatenated bundles with missing newlines between blocks; expired tooling emitting malformed armor.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Failed to create identity from cert and key: {}
- Failed to read CA certificate: {}
- Failed to parse PEM key: {}
- Failed to encode PKCS#8: {}
- Invalid model spec '{}': expected format 'user/repo:quantiza
AI-assisted analysis of aaif-goose/goose@3810898a74 (2026-08-16).
Data as JSON: /api/errors/c72dd30c46f2ca20.
Report an issue: GitHub.