coollabsio/coolify · error · Exception

Failed to generate new {$type} key: {message}

Error message

Failed to generate new {$type} key: {message}

What it means

Thrown by PrivateKey::generateNewKeyPair() (app/Models/PrivateKey.php:178). This static helper rate-limits itself ($instance->rateLimit(10)), maps the requested type to 'ed25519' or 'rsa', then shells out via generateSSHKey($type). Any Throwable — a rate-limit exception, a missing ssh-keygen binary, or a process error — is caught and re-wrapped as "Failed to generate new {$type} key: {message}". Note the rate limiter (10 attempts) throws TooManyAttemptsException, which is a Throwable, so hitting the limit also surfaces through this message with a misleading 'key generation' framing.

Source

Thrown at app/Models/PrivateKey.php:178

    }

    public static function generateNewKeyPair($type = 'rsa')
    {
        try {
            $instance = new self;
            $instance->rateLimit(10);
            $name = generate_random_name();
            $description = 'Created by Coolify';
            $keyPair = generateSSHKey($type === 'ed25519' ? 'ed25519' : 'rsa');

            return [
                'name' => $name,
                'description' => $description,
                'private_key' => $keyPair['private'],
                'public_key' => $keyPair['public'],
            ];
        } catch (\Throwable $e) {
            throw new \Exception("Failed to generate new {$type} key: ".$e->getMessage());
        }
    }

    public static function extractPublicKeyFromPrivate($privateKey)
    {
        try {
            $key = PublicKeyLoader::load($privateKey);

            return $key->getPublicKey()->toString('OpenSSH', ['comment' => '']);
        } catch (\Throwable $e) {
            return null;
        }
    }

    public static function validateAndExtractPublicKey($privateKey)
    {
        $isValid = self::validatePrivateKey($privateKey);
        $publicKey = $isValid ? self::extractPublicKeyFromPrivate($privateKey) : '';

View on GitHub (pinned to 70b9acc424)

Solutions

  1. If you generated several keys recently, wait for the rate-limit window to decay (limit is 10) and retry.
  2. Verify ssh-keygen exists in the container: docker exec coolify which ssh-keygen.
  3. Check the appended {message} — it distinguishes 'Too many attempts' from an ssh-keygen/exec failure.
  4. Only pass 'rsa' or 'ed25519'; other values are silently coerced to rsa but the message will echo your original $type.

Example fix

// before
for ($i = 0; $i < 15; $i++) {
    $pair = PrivateKey::generateNewKeyPair('ed25519'); // trips 10/attempt limit
}

// after — pace generation or use RateLimiter::tooManyAttempts to precheck
use Illuminate\Support\Facades\RateLimiter;
if (RateLimiter::tooManyAttempts('generate-key:'.auth()->id(), 10)) {
    return back()->withErrors(['key' => 'Slow down — key generation is rate limited.']);
}
$pair = PrivateKey::generateNewKeyPair('ed25519');
Defensive patterns

Strategy: retry

Validate before calling

// Pre-check the rate limit used by generateNewKeyPair
use Illuminate\Support\Facades\RateLimiter;
$key = 'generate-key:'.(auth()->id() ?? 'system');
if (RateLimiter::tooManyAttempts($key, 10)) {
    $seconds = RateLimiter::availableIn($key);
    abort(429, "Key generation rate limited. Retry in {$seconds}s.");
}

Try / catch

try {
    $pair = PrivateKey::generateNewKeyPair('ed25519');
} catch (\Exception $e) {
    if (str_contains($e->getMessage(), 'Too Many Attempts')) {
        // back off and retry after RateLimiter::availableIn()
        return retry(after: fn () => RateLimiter::availableIn($key), callback: fn () => PrivateKey::generateNewKeyPair('ed25519'));
    }
    throw $e; // ssh-keygen/exec failure — check binary availability
}

Prevention

When it happens

Trigger: Calling PrivateKey::generateNewKeyPair('ed25519') or ('rsa') more than 10 times in a short window (rate limit), or when ssh-keygen is absent/broken in the Coolify container, or the temp area used by generateSSHKey() is not writable.

Common situations: UI/script generating many key pairs in a loop (e.g. seeding servers) and tripping the 10-per-window limiter; slim/custom Coolify images without openssh-client; read-only /tmp inside the container.

Related errors


AI-assisted analysis of coollabsio/coolify@70b9acc424 (2026-08-17). Data as JSON: /api/errors/d133031e02b6b96f. Report an issue: GitHub.