juicedata/juicefs · error

passphrase is required to private key

Error message

passphrase is required to private key

What it means

ErrKeyNeedPasswd is returned by ParsePrivateKeyFromPem when the supplied RSA private key is encrypted (PEM) but no passphrase was given (empty JFS_RSA_PASSPHRASE). The key cannot be decrypted, so format/load abort with a hint to set the env var.

Source

Thrown at pkg/object/encrypt.go:65

func ExportRsaPrivateKeyToPem(key *rsa.PrivateKey, passphrase string) string {
	buf := x509.MarshalPKCS1PrivateKey(key)
	block := &pem.Block{
		Type:  "RSA PRIVATE KEY",
		Bytes: buf,
	}
	if passphrase != "" {
		var err error
		// nolint:staticcheck
		block, _ = x509.EncryptPEMBlock(rand.Reader, block.Type, buf, []byte(passphrase), x509.PEMCipherAES256)
		if err != nil {
			panic(err)
		}
	}
	privPEM := pem.EncodeToMemory(block)
	return string(privPEM)
}

var ErrKeyNeedPasswd = errors.New("passphrase is required to private key")

func ParsePrivateKeyFromPem(enc []byte, passphrase []byte) (any, error) {
	block, _ := pem.Decode(enc)
	if block == nil {
		return nil, errors.New("failed to parse PEM block containing the key")
	}

	buf := block.Bytes
	if len(passphrase) == 0 {
		// nolint:staticcheck
		if strings.Contains(block.Headers["Proc-Type"], "ENCRYPTED") && x509.IsEncryptedPEMBlock(block) {
			return nil, ErrKeyNeedPasswd
		}
		if strings.Contains(block.Type, "ENCRYPTED") {
			return nil, ErrKeyNeedPasswd
		}
	} else {
		var err error

View on GitHub (pinned to c9a67b23e8)

Solutions

  1. Set the JFS_RSA_PASSPHRASE environment variable to the key's passphrase before running the command.
  2. Verify with errors.Is(err, object.ErrKeyNeedPasswd) to distinguish from other key parse errors and print the hint.
  3. If no passphrase should be needed, supply an unencrypted RSA private key PEM instead.
  4. Ensure the env var is passed through sudo/systemd/cron (sudo -E, Environment=, or export in the job).

Example fix

// before
juicefs format sqlite3://test.db myjfs --encrypt-algo rsa-keygen --encrypt-key key.pem
// after
export JFS_RSA_PASSPHRASE='my-secret'
juicefs format sqlite3://test.db myjfs --encrypt-algo rsa-keygen --encrypt-key key.pem
Defensive patterns

Strategy: try-catch

Validate before calling

if len(os.Getenv("JFS_RSA_PASSPHRASE")) == 0 && keyIsEncrypted(keyPEM) {
    return fmt.Errorf("set JFS_RSA_PASSPHRASE before using encrypted key")
}

Try / catch

privKey, err := object.ParsePrivateKeyFromPem(key, []byte(os.Getenv("JFS_RSA_PASSPHRASE")))
if errors.Is(err, object.ErrKeyNeedPasswd) {
    return nil, fmt.Errorf("%w: please set the 'JFS_RSA_PASSPHRASE' environment variable", err)
}

Prevention

When it happens

Trigger: juicefs format --encrypt-algo with an encrypted private key while JFS_RSA_PASSPHRASE is unset; juicefs load on an encrypted backup without the env var; createStorage/open wrapping a sync-encrypted store without a passphrase.

Common situations: Running format/load in cron/CI where the env var isn't exported; key generated with openssl with a password but the operator forgot the env var; service accounts lacking the secret.

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06). Data as JSON: /api/errors/b5d1a619a66ba520. Report an issue: GitHub.