beemdevelopment/Aegis · error
Secret is empty
Error message
Secret is empty
What it means
Thrown by GoogleAuthInfo.parseUri(Uri) after 'secret' decodes to a zero-length byte array. The URI passed the scheme and secret-presence checks, but the secret value itself (base32 or hex) decodes to nothing, e.g. an empty or all-whitespace secret parameter, so no valid OTP key can be constructed.
Solutions
- Provide the actual Base32 secret in the URI's secret parameter
- Check the upstream configuration/variable feeding the URI for emptiness
- Validate the secret is non-empty before constructing the URI
Example fix
// before
String uri = "otpauth://totp/x?secret=";
// after
if (secret == null || secret.isEmpty()) throw new IllegalArgumentException("secret required");
String uri = "otpauth://totp/x?secret=" + secret; Defensive patterns
Strategy: validation
Validate before calling
String p = uri.getQueryParameter("secret"); if (p == null || p.replaceAll("=", "").isEmpty()) throw new IllegalArgumentException("secret empty"); Try / catch
try { return GoogleAuthInfo.parseUri(uri); } catch (GoogleAuthInfoException e) { reportIncompleteUri(uri); return null; } Prevention
- Check the secret source variable isn't empty before building URIs
- Reject template URIs with unfilled placeholders
- Validate decoded secret length > 0 before import
When it happens
Trigger: parseUri(Uri) with secret= (empty string) or a value consisting only of Base32 padding '=' characters.
Common situations: URI templates left un-filled (secret=), scripts building URIs from an empty secret variable, or corrupt QR payloads.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- Secret cannot be empty
- bad period
- Invalid Yandex secret length
- Period is not an integer.
- Secret is a required field.
AI-assisted analysis of beemdevelopment/Aegis@d6f4e5925a (2026-09-08).
Data as JSON: /api/errors/d5c112a2f1a21e4d.
Report an issue: GitHub.
Appendix: source
Thrown at app/src/main/java/com/beemdevelopment/aegis/otp/GoogleAuthInfo.java:63
String scheme = uri.getScheme();
if (scheme == null || !(scheme.equals(SCHEME) || scheme.equals(MotpInfo.SCHEME))) {
throw new GoogleAuthInfoException(uri, String.format("Unsupported protocol: %s", scheme));
}
// 'secret' is a required parameter
String encodedSecret = uri.getQueryParameter("secret");
if (encodedSecret == null) {
throw new GoogleAuthInfoException(uri, "Parameter 'secret' is not present");
}
byte[] secret;
try {
secret = (scheme.equals(MotpInfo.SCHEME)) ? Hex.decode(encodedSecret) : parseSecret(encodedSecret);
} catch (EncodingException e) {
throw new GoogleAuthInfoException(uri, "Bad secret", e);
}
if (secret.length == 0) {
throw new GoogleAuthInfoException(uri, "Secret is empty");
}
OtpInfo info;
String issuer = "";
try {
String type = (scheme.equals(MotpInfo.SCHEME)) ? MotpInfo.ID : uri.getHost();
if (type == null) {
throw new GoogleAuthInfoException(uri, String.format("Host not present in URI: %s", uri.toString()));
}
switch (type) {
case "totp":
TotpInfo totpInfo = new TotpInfo(secret);
String period = uri.getQueryParameter("period");
if (period != null) {
totpInfo.setPeriod(Integer.parseInt(period));
}
info = totpInfo;View on GitHub (pinned to d6f4e5925a)