juicedata/juicefs · error

%w: please set the 'JFS_RSA_PASSPHRASE' environment variable

Error message

%w: please set the 'JFS_RSA_PASSPHRASE' environment variable

What it means

The configured encryption key is a passphrase-protected RSA private key, and no passphrase was supplied. ParsePrivateKeyFromPem returned ErrKeyNeedPasswd, which createStorage wraps with instructions to set the JFS_RSA_PASSPHRASE environment variable.

Source

Thrown at cmd/format.go:293

			object.GetHttpClient().Transport.(*http.Transport).TLSClientConfig.Certificates = []tls.Certificate{clientTLSCert}
		}
	}

	if format.Shards > 1 {
		blob, err = object.NewSharded(strings.ToLower(format.Storage), format.Bucket, format.AccessKey, format.SecretKey, format.SessionToken, format.Shards)
	} else {
		blob, err = object.CreateStorage(strings.ToLower(format.Storage), format.Bucket, format.AccessKey, format.SecretKey, format.SessionToken)
	}
	if err != nil {
		return nil, err
	}
	blob = object.WithPrefix(blob, format.Name+"/")
	initStorageTiers(blob, format.Tiers)
	if format.EncryptKey != "" {
		privKey, err := object.ParsePrivateKeyFromPem([]byte(format.EncryptKey), []byte(os.Getenv("JFS_RSA_PASSPHRASE")))
		if err != nil {
			if errors.Is(err, object.ErrKeyNeedPasswd) {
				return nil, fmt.Errorf("%w: please set the 'JFS_RSA_PASSPHRASE' environment variable", err)
			}
			return nil, fmt.Errorf("parse private key: %s", err)
		}
		encryptor, err := object.NewDataEncryptor(object.NewKeyEncryptor(privKey), format.EncryptAlgo)
		if err != nil {
			return nil, err
		}
		blob = object.NewEncrypted(blob, encryptor)
	}
	return blob, nil
}

func initStorageTiers(storage object.ObjectStorage, tiers object.Tiers) {
	if tierStorage, ok := storage.(object.SupportTier); ok {
		if err := tierStorage.InitTiers(tiers); err != nil && hasConfiguredTiers(tiers) {
			logger.Warnf("Set storage tier: %s", err)
		}
	}

View on GitHub (pinned to c9a67b23e8)

Solutions

  1. Export the variable before running: `export JFS_RSA_PASSPHRASE='your-passphrase'` then re-run the command
  2. Generate a passphrase-free key if acceptable: `openssl rsa -in key.pem -out key-nocrypt.pem`
  3. Pass the env var inline: `JFS_RSA_PASSPHRASE='...' juicefs format ...`
  4. For services, add `Environment=JFS_RSA_PASSPHRASE=...` or use an EnvironmentFile/secret manager

Example fix

// before
juicefs format --encrypt-key key.pem ...
// after
export JFS_RSA_PASSPHRASE='secret'
juicefs format --encrypt-key key.pem ...
Defensive patterns

Strategy: validation

Validate before calling

if os.Getenv("JFS_RSA_PASSPHRASE") == "" {
    if keyData, _ := os.ReadFile(keyPath); strings.Contains(string(keyData), "ENCRYPTED") {
        return fmt.Errorf("key %s is encrypted; set JFS_RSA_PASSPHRASE", keyPath)
    }
}

Type guard

func keyNeedsPassphrase(pemBytes []byte) bool {
    return strings.Contains(string(pemBytes), "ENCRYPTED") ||
        strings.Contains(string(pemBytes), "Proc-Type: 4,ENCRYPTED")
}

Try / catch

_, err := createStorage(...)
if err != nil && errors.Is(err, object.ErrKeyNeedPassphrase) {
    // prompt for or load JFS_RSA_PASSPHRASE and retry
}

Prevention

When it happens

Trigger: `juicefs format` with an --encrypt-key file generated via `openssl genrsa -aes...` (or ssh-keygen with a passphrase) while the JFS_RSA_PASSPHRASE environment variable is unset or empty.

Common situations: Encrypt-at-rest volumes set up interactively on one machine then used from CI/containers where the env var was never exported; passphrase rotated but env var stale; systemd units missing Environment= line.

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/fd9755dc378b5168. Report an issue: GitHub.