cloudflare/cloudflared · error

%d: %s

Error message

%d: %s

What it means

SignCert calls cloudflared's certificate-signing service and expects a 200 response. On a non-200 status it attempts to decode an errorResponse body and returns '<status>: <message>' so the caller (handleCertificateGeneration) sees the HTTP status code and the service's error message describing why the CSR could not be signed.

Solutions

  1. Inspect the numeric status in the error message: 401/403 means fix your API token/credentials, 400 means fix the CSR or request payload.
  2. Regenerate or refresh the API token used by `cloudflared access ssh-gen` / certificate generation.
  3. Validate the CSR (algorithm, principals) before submission; re-generate with a supported key type (e.g. ed25519).
  4. If the status is 429/5xx, wait and retry; check the Cloudflare status page for incidents.
  5. Capture the full error and Cloudflare support details (account/tag) if the problem persists.
Defensive patterns

Strategy: validation

Validate before calling

// client side: avoid UDP ASSOCIATE; TCP CONNECT only
if cmd == socks.CmdAssociate {
	return errors.New("cloudflared socks5 does not support UDP ASSOCIATE")
}

Try / catch

if err := sendReply(conn, commandNotSupported, nil); err != nil {
	return fmt.Errorf("failed to send ASSOCIATE refusal: %w", err)
}

Prevention

When it happens

Trigger: The remote sign service returns a non-200 status with a JSON error body (e.g. 400 for a malformed CSR, 401/403 for bad credentials/token, 429 rate limit, 5xx server error), and the body successfully decodes into errorResponse.

Common situations: Expired or missing Cloudflare API token when requesting SSH certificates; uploading a CSR with an unsupported key type or invalid principal; Cloudflare SSH infrastructure returning transient 5xx; corporate proxies injecting HTML error pages that still decode oddly or fail decode and surface the raw error instead.

Related errors


AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06). Data as JSON: /api/errors/7705c02df703e7b1. Report an issue: GitHub.

Appendix: source

Thrown at sshgen/sshgen.go:134

		client := http.Client{
			Timeout: 10 * time.Second,
		}
		res, err = client.Post(claims.Issuer+signEndpoint, "application/json", bytes.NewBuffer(buf))
	}

	if err != nil {
		return "", errors.Wrap(err, "failed to send request")
	}
	defer res.Body.Close()

	decoder := json.NewDecoder(res.Body)

	if res.StatusCode != 200 {
		var errResponse errorResponse
		if err := decoder.Decode(&errResponse); err != nil {
			return "", err
		}
		return "", fmt.Errorf("%d: %s", errResponse.Status, errResponse.Message)
	}

	var signRes signResponse
	if err := decoder.Decode(&signRes); err != nil {
		return "", errors.Wrap(err, "failed to decode HTTP response")
	}
	return signRes.Certificate, nil
}

// generateKeyPair creates a EC keypair (P256) and stores them in the homedir.
// returns the generated public key from the successful keypair generation
func generateKeyPair(fullName string) ([]byte, error) {
	pubKeyName := fullName + ".pub"

	exist, err := config.FileExists(pubKeyName)
	if err != nil {
		return nil, err
	}

View on GitHub (pinned to 2253eeeb25)