docker/cli ยท error

CA cert for external CA must be in PEM format

Error message

CA cert for external CA must be in PEM format

What it means

Raised while parsing an `--external-ca` specification when the file given via the `cacert=` field reads successfully but contains no decodable PEM block. parseExternalCA validates the external CA's certificate client-side with pem.Decode before including it in the swarm spec.

Source

Thrown at cli/command/swarm/opts.go:201

		// TODO(thaJeztah): these options should not be case-insensitive.
		switch strings.ToLower(key) {
		case "protocol":
			hasProtocol = true
			if strings.ToLower(value) == string(swarm.ExternalCAProtocolCFSSL) {
				externalCA.Protocol = swarm.ExternalCAProtocolCFSSL
			} else {
				return nil, fmt.Errorf("unrecognized external CA protocol %s", value)
			}
		case "url":
			hasURL = true
			externalCA.URL = value
		case "cacert":
			cacontents, err := os.ReadFile(value)
			if err != nil {
				return nil, fmt.Errorf("unable to read CA cert for external CA: %w", err)
			}
			if pemBlock, _ := pem.Decode(cacontents); pemBlock == nil {
				return nil, errors.New("CA cert for external CA must be in PEM format")
			}
			externalCA.CACert = string(cacontents)
		default:
			externalCA.Options[key] = value
		}
	}

	if !hasProtocol {
		return nil, errors.New("the external-ca option needs a protocol= parameter")
	}
	if !hasURL {
		return nil, errors.New("the external-ca option needs a url= parameter")
	}

	return &externalCA, nil
}

func addSwarmCAFlags(flags *pflag.FlagSet, options *swarmCAOptions) {

View on GitHub (pinned to e9452d6e78)

Solutions

  1. Verify the cacert file begins with `-----BEGIN CERTIFICATE-----`.
  2. Convert to PEM if needed: `openssl x509 -inform der -in ca.crt -out ca.pem`.
  3. Ensure the path in `cacert=` points to the intended, non-empty file.
  4. Re-run the swarm init/update with the corrected file.

Example fix

# before
docker swarm update --external-ca protocol=cfssl,url=https://ca.example.com,cacert=ca.der
# after
openssl x509 -inform der -in ca.der -out ca.pem
docker swarm update --external-ca protocol=cfssl,url=https://ca.example.com,cacert=ca.pem

When it happens

Trigger: `docker swarm init` or `docker swarm update` with `--external-ca protocol=cfssl,url=...,cacert=<file>` where the referenced file is DER-encoded, empty, truncated, or otherwise missing a `-----BEGIN ...-----` PEM block.

Common situations: Downloading a CA certificate from an internal PKI in DER format; passing a bundle in PKCS#7/PKCS#12 format; a deployment templating step writing an empty cacert file; wrong filename in automation.

Related errors


AI-assisted analysis of docker/cli@e9452d6e78 (2026-08-01). Data as JSON: /data/errors/5330930cf15e12c2.json. Report an issue: GitHub.