quarkusio/quarkus · error · RuntimeException
Unable to read the account file, you must create account fir
Error message
Unable to read the account file, you must create account first
What it means
readAccountJson reads <letsEncryptPath>/account.json, which saveAccount writes during account creation. If the file cannot be opened or read (typically because it does not exist), this RuntimeException tells the user they must run account creation first. No underlying exception is chained; the message is the entire diagnostic.
Source
Thrown at extensions/tls-registry/cli/src/main/java/io/quarkus/tls/cli/letsencrypt/LetsEncryptHelpers.java:249
builder.setKey(certificate, privateKey);
}
AcmeAccount acmeAccount = builder.build();
acmeAccount.setContactUrls(new String[] { json.getString("contact-url") });
acmeAccount.setAccountUrl(json.getString("account-url"));
return acmeAccount;
}
private static JsonObject readAccountJson(File letsEncryptPath) {
LOGGER.debugf("Reading account information from %s", letsEncryptPath);
java.nio.file.Path accountPath = Paths.get(letsEncryptPath + "/account.json");
try (FileInputStream fis = new FileInputStream(accountPath.toString())) {
return new JsonObject(new String(fis.readAllBytes(), StandardCharsets.US_ASCII));
} catch (IOException e) {
throw new RuntimeException("Unable to read the account file, you must create account first");
}
}
private static X509Certificate getCertificate(String encodedCert) {
try {
byte[] encodedBytes = Base64.getDecoder().decode(encodedCert);
return (X509Certificate) CertificateFactory.getInstance("X.509")
.generateCertificate(new ByteArrayInputStream(encodedBytes));
} catch (Exception ex) {
throw new RuntimeException("Failure to create a certificate", ex);
}
}
private static PrivateKey getPrivateKey(String encodedKey, String keyAlgorithm) {
try {
KeyFactory f = KeyFactory.getInstance((keyAlgorithm == null || "RSA".equals(keyAlgorithm) ? "RSA" : "EC"));
byte[] encodedBytes = Base64.getDecoder().decode(encodedKey);
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(encodedBytes);View on GitHub (pinned to e1c734241f)
Solutions
- Create the ACME account first (run the create-account command / LetsEncryptHelpers.createAccount) so account.json is written
- Verify letsEncryptPath points to the directory that actually contains account.json
- Check file permissions so the current user can read account.json
- If the account was stored on ephemeral storage (container), persist the letsencrypt directory as a volume
Example fix
// before: reading account before it exists
JsonObject json = LetsEncryptHelpers.json(new File("/etc/quarkus/letsencrypt")); // RuntimeException
// after: create the account first
LetsEncryptHelpers.createAccount(acmeClient, new File("/etc/quarkus/letsencrypt"), true, "my@example.com");
JsonObject json = LetsEncryptHelpers.json(new File("/etc/quarkus/letsencrypt")); Defensive patterns
Strategy: validation
Validate before calling
File dir = letsEncryptPath;
File accountFile = new File(dir, "account.json");
if (!accountFile.isFile() || !accountFile.canRead()) {
throw new IllegalStateException("ACME account not found at " + accountFile + "; create the account first");
}
JsonObject json = LetsEncryptHelpers.json(dir); Type guard
boolean hasAcmeAccount(File letsEncryptPath) {
File f = new File(letsEncryptPath, "account.json");
return f.isFile() && f.canRead() && f.length() > 0;
} Try / catch
try {
JsonObject json = LetsEncryptHelpers.json(letsEncryptPath);
} catch (RuntimeException e) {
if (e.getMessage() != null && e.getMessage().contains("Unable to read the account file")) {
// account was never created or path is wrong — run account creation flow
throw new IllegalStateException("No ACME account at " + letsEncryptPath + "/account.json. Run create-account first.", e);
}
throw e;
} Prevention
- Always run account creation before renewal/lookup commands
- Persist the letsencrypt directory across container restarts (volume mount)
- Verify the letsEncryptPath matches the one used at account creation
- Check account.json readability after deployments or permission changes
When it happens
Trigger: Calling the json() method (or any flow calling readAccountJson) before createAccount has ever run, or pointing at a letsEncryptPath directory that contains no account.json.
Common situations: Running 'renew' or account-inspection commands on a fresh machine/checkout without 'create account' first; mistyped or changed letsencrypt directory path; account.json deleted by cleanup scripts or container restarts on ephemeral storage.
Related errors
- Failure to save the account
- Unable to read the template content from path: <path>
- Rate limit exceeded: too many ACME challenge requests. Wait
- Missing certificate authority challenge
- Invalid certificate authority challenge
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/f9b13a09f280fcef.
Report an issue: GitHub.