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.

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)

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.