beemdevelopment/Aegis · error
Unsupported OtpInfo type
Error message
Unsupported OtpInfo type: %s
What it means
getUri builds an otpauth:// URI from an OtpInfo; it only knows TotpInfo and HotpInfo subclasses. If _info is neither (a custom or future OtpInfo subclass), a RuntimeException is thrown because there is no standard URI encoding for it. This is an internal invariant rather than bad user input.
Solutions
- Only pass TotpInfo/HotpInfo entries to getUri; filter or convert other types first
- Skip unsupported entry types during export instead of failing the whole batch
- Extend the if/else chain to handle the custom OtpInfo type or subclass TotpInfo/HotpInfo
Example fix
// before
GoogleAuthInfo.getUri(entry); // entry.getInfo() is a custom MotpInfo
// after
if (entry.getInfo() instanceof TotpInfo || entry.getInfo() instanceof HotpInfo) {
GoogleAuthInfo.getUri(entry);
} else {
continue; // skip unsupported type
} Defensive patterns
Strategy: type-guard
Validate before calling
if (!(info instanceof TotpInfo) && !(info instanceof HotpInfo)) {
throw new IllegalArgumentException("Only TOTP/HOTP entries can be exported");
} Type guard
boolean exportable(VaultEntry e) {
return e.getInfo() instanceof TotpInfo || e.getInfo() instanceof HotpInfo;
} Try / catch
try {
uri = GoogleAuthInfo.getUri(entry);
} catch (RuntimeException e) {
Log.w(TAG, "Skipping non-exportable entry: " + e.getMessage());
} Prevention
- Filter entries to TotpInfo/HotpInfo before export
- Handle fork-specific OtpInfo types separately
- Wrap getUri per entry so one bad type skips rather than aborts
When it happens
Trigger: Calling GoogleAuthInfo.getUri (directly or via export/exportGoogleUris) on an entry whose OtpInfo is neither TotpInfo nor HotpInfo.
Common situations: Custom OtpInfo subclasses added by forks (e.g. Steam or Yandex types) passed into the Google export path, or future info types from library updates not yet handled here.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- unsupported otp type:
- unsupported otp type:
- unsupported otp type:
- Unrecognized tokenType
- Unsupported OTP type
AI-assisted analysis of beemdevelopment/Aegis@d6f4e5925a (2026-09-08).
Data as JSON: /api/errors/159f4c7f07453617.
Report an issue: GitHub.
Appendix: source
Thrown at app/src/main/java/com/beemdevelopment/aegis/otp/GoogleAuthInfo.java:301
builder.scheme(MotpInfo.SCHEME);
builder.appendQueryParameter("secret", Hex.encode(_info.getSecret()));
} else {
builder.scheme(SCHEME);
if (_info instanceof TotpInfo) {
if (_info instanceof SteamInfo) {
builder.authority("steam");
} else if (_info instanceof YandexInfo) {
builder.authority(YandexInfo.HOST_ID);
} else {
builder.authority("totp");
}
builder.appendQueryParameter("period", Integer.toString(((TotpInfo) _info).getPeriod()));
} else if (_info instanceof HotpInfo) {
builder.authority("hotp");
builder.appendQueryParameter("counter", Long.toString(((HotpInfo) _info).getCounter()));
} else {
throw new RuntimeException(String.format("Unsupported OtpInfo type: %s", _info.getClass()));
}
builder.appendQueryParameter("digits", Integer.toString(_info.getDigits()));
builder.appendQueryParameter("algorithm", _info.getAlgorithm(false));
builder.appendQueryParameter("secret", Base32.encode(_info.getSecret()));
if (_info instanceof YandexInfo) {
builder.appendQueryParameter("pin", Base32.encode(((YandexInfo) _info).getPin()));
}
}
if (_issuer != null && !_issuer.equals("")) {
builder.path(String.format("%s:%s", _issuer, _accountName));
builder.appendQueryParameter("issuer", _issuer);
} else {
builder.path(_accountName);
}
View on GitHub (pinned to d6f4e5925a)