JuliusBrussee/caveman · error

githubapp: private key PEM is required

Error message

githubapp: private key PEM is required

What it means

Configuration guard in githubapp.New: the app's private key PEM is empty, so installation tokens cannot be signed and the App fails closed as unconfigured. The GITHUB_APP private key configuration is at fault.

Source

Thrown at shared/platform/githubapp/githubapp.go:72

type App struct {
	appID         string
	slug          string
	privateKey    *rsa.PrivateKey
	webhookSecret string
	baseURL       string
	httpClient    *http.Client
}

// New parses the private key, validates the base URL, and builds the App. It
// returns an error (not a half-built App) on any misconfiguration, so callers
// fail closed — an unconfigured deployment leaves the App nil and the connect
// endpoints answer a clean "disabled" rather than a fabricated success.
func New(cfg Config) (*App, error) {
	if strings.TrimSpace(cfg.AppID) == "" {
		return nil, fmt.Errorf("githubapp: app id is required")
	}
	if len(cfg.PrivateKeyPEM) == 0 {
		return nil, fmt.Errorf("githubapp: private key PEM is required")
	}
	key, err := parseRSAPrivateKey(cfg.PrivateKeyPEM)
	if err != nil {
		return nil, err
	}
	base := strings.TrimRight(strings.TrimSpace(cfg.BaseURL), "/")
	if base == "" {
		base = defaultBaseURL
	}
	client := cfg.HTTPClient
	if client == nil {
		// Production path: SSRF-guarded client + pre-flight host check on a custom
		// (GHE) base. When a caller injects a client (tests), it owns the host policy,
		// so we skip the pre-flight — but production never injects one.
		if base != defaultBaseURL {
			if err := ssrf.ValidateURL(context.Background(), base, ssrf.ManagedConfig()); err != nil {
				return nil, fmt.Errorf("githubapp: base_url rejected by SSRF guard: %w", err)
			}

View on GitHub (pinned to 766dce6b13)

Solutions

  1. Supply the GitHub App private key PEM in Config (downloaded from the App settings page)
  2. Verify the secret mount/env injection actually delivered the key contents, not an empty value
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at shared/platform/githubapp/githubapp.go:72 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of JuliusBrussee/caveman@766dce6b13 (2026-08-18). Data as JSON: /api/errors/f5c6d752cc1ec64f. Report an issue: GitHub.