n8n-io/n8n · error · Error
The Certificate field must contain a PEM certificate (-----B
Error message
The Certificate field must contain a PEM certificate (-----BEGIN CERTIFICATE-----).
What it means
Thrown by certificateThumbprint in buildClientAssertion when `new X509Certificate(formatPemBlock(cert))` raises. The wrapper message tells the caller the certificate field must be a PEM certificate; the original crypto error is preserved as `cause`. The certificate is used to compute the x5t (SHA-1 thumbprint) JWT header.
Source
Thrown at packages/@n8n/utils/src/client-assertion.ts:27
import { formatPemBlock } from './format-pem-block';
// private_key_jwt (RFC 7521/7523): the client proves its identity with a JWT
// signed by its private key instead of a shared secret. The `x5t` header (SHA-1
// thumbprint of the certificate) tells the server which public key verifies it.
export const CLIENT_ASSERTION_TYPE = 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer';
const ASSERTION_TTL_SECONDS = 300;
function base64url(input: Buffer | string): string {
return Buffer.from(input).toString('base64url');
}
function certificateThumbprint(certificate: string): string {
let parsed: X509Certificate;
try {
parsed = new X509Certificate(formatPemBlock(certificate));
} catch (error) {
throw new Error(
'The Certificate field must contain a PEM certificate (-----BEGIN CERTIFICATE-----).',
{ cause: error },
);
}
return Buffer.from(parsed.fingerprint.replace(/:/g, ''), 'hex').toString('base64url');
}
export interface BuildClientAssertionOptions {
clientId: string;
/** Token endpoint; used as the JWT `aud`. */
accessTokenUri: string;
/** RSA private key (PEM). Signing is RS256-only; EC/Ed25519 keys are not supported. */
privateKey: string;
certificate: string;
}
export function buildClientAssertion(options: BuildClientAssertionOptions): string {
const now = Math.floor(Date.now() / 1000);View on GitHub (pinned to 5ac6606e81)
Solutions
- Verify the certificate begins with '-----BEGIN CERTIFICATE-----' and ends with the matching END marker.
- Ensure you are passing the public certificate, not the private key.
- Validate with `openssl x509 -in cert.pem -noout` before configuring.
- Inspect err.cause for the underlying crypto reason to pinpoint the format issue.
Example fix
// before
buildClientAssertion({ ..., certificate: privateKeyPem }); // wrong field content
// after
buildClientAssertion({ ..., certificate: publicCertPem }); // -----BEGIN CERTIFICATE-----... Defensive patterns
Strategy: validation
Validate before calling
function assertValidCertificatePem(cert: string): void {
if (!cert || !/-----BEGIN CERTIFICATE-----/.test(cert) || !/-----END CERTIFICATE-----/.test(cert)) {
throw new Error('certificate must be a PEM string bounded by BEGIN/END CERTIFICATE markers');
}
// optionally verify it parses:
new X509Certificate(cert); // throws on malformed input
} Type guard
function looksLikePemCertificate(v: unknown): v is string {
return typeof v === 'string'
&& /-----BEGIN CERTIFICATE-----[\s\S]*-----END CERTIFICATE-----/.test(v);
} Try / catch
try {
return buildClientAssertion(opts);
} catch (e) {
if (/must contain a PEM certificate/i.test(e?.message ?? '')) {
throw new ConfigError('certificate field is not a valid PEM certificate', { cause: e });
}
throw e;
} Prevention
- Validate the PEM markers before calling buildClientAssertion.
- Keep the certificate (public) and private key fields clearly labeled in config UIs.
- Verify with `openssl x509 -in cert.pem -noout` during onboarding.
When it happens
Trigger: Passing an empty certificate string, a private key PEM instead of a certificate PEM, a DER/base64 blob without the BEGIN CERTIFICATE markers, a certificate for the wrong key, or a malformed/truncated PEM.
Common situations: Uploading the private key into the certificate field by mistake in a config UI; copy-paste truncating the END marker; using a self-signed cert in a format Node's crypto cannot parse; passing a cert chain where a single leaf is expected without formatPemBlock-friendly input.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- The Private Key field must contain a PEM private key (-----B
- Certificate authentication requires an RSA private key
- Unknown algorithm ${algorithm}. Available algorithms are: ${
- Cannot decrease maxIterations when resuming a run. Expected
- Checkpoint for runId ${this.runId} has pending tool calls —
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/edd1262ccc8e176e.
Report an issue: GitHub.