beemdevelopment/Aegis · error

Unrecognized tokenType

Error message

Unrecognized tokenType: %s

What it means

TwoFASImporter.convertEntry converts a 2FAS backup entry into an Aegis vault entry. It recognizes tokenType values TOTP, HOTP, and STEAM; any other tokenType string makes it throw DatabaseImporterEntryException, meaning the 2FAS backup contains a token type this importer doesn't know how to map.

Solutions

  1. Update Aegis to the latest version, which may support the new 2FAS tokenType.
  2. Open the 2FAS backup and check the entry's tokenType value; re-create the token in 2FAS as a standard TOTP/HOTP and re-export.
  3. Convert the token manually in Aegis by entering its secret and parameters (algorithm, digits, period).
  4. If the type is legitimately supported by 2FAS, add an else-if branch in convertEntry mapping it to the correct OtpInfo subclass.

Example fix

// before
} else {
    throw new DatabaseImporterEntryException(String.format("Unrecognized tokenType: %s", tokenType), obj.toString());
}
// after: handle a new type instead of failing
} else if (tokenType.equals("MOBILE_OTD")) {
    otp = new TotpInfo(secret, algorithm, digits, period);
} else {
    throw new DatabaseImporterEntryException(String.format("Unrecognized tokenType: %s", tokenType), obj.toString());
}
Defensive patterns

Strategy: validation

Validate before calling

// Validate tokenType before conversion
Set<String> supported = new HashSet<>(Arrays.asList("TOTP", "HOTP", "STEAM"));
String tokenType = info.optString("tokenType", "");
if (!supported.contains(tokenType)) {
    reportSkippedEntry(obj, "unsupported tokenType: " + tokenType);
}

Type guard

boolean isSupportedTokenType(String tokenType) {
    return "TOTP".equals(tokenType) || "HOTP".equals(tokenType) || "STEAM".equals(tokenType);
}

Try / catch

try {
    entry = convertEntry(obj);
} catch (DatabaseImporterEntryException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("Unrecognized tokenType")) {
        logSkippedEntry(obj, e.getMessage()); // skip entry, continue import
    }
}

Prevention

When it happens

Trigger: Importing a 2FAS backup JSON whose entry's tokenType is not exactly "TOTP", "HOTP", or "STEAM" — e.g. newer 2FAS app versions introducing new token types (like mobile OTP or service-specific types), or a manually edited backup.

Common situations: Users upgrading 2FAS to a version that writes new tokenType values, then importing the new backup into Aegis; hand-edited backups with inconsistent casing ("totp"); backups from beta 2FAS releases.

Related errors


AI-assisted analysis of beemdevelopment/Aegis@d6f4e5925a (2026-09-08). Data as JSON: /api/errors/a6f4dc01d8589378. Report an issue: GitHub.

Appendix: source

Thrown at app/src/main/java/com/beemdevelopment/aegis/importers/TwoFASImporter.java:199

                    issuer = info.optString("issuer");
                }
                String name = info.optString("account");
                int digits = info.optInt("digits", TotpInfo.DEFAULT_DIGITS);
                String algorithm = info.optString("algorithm", TotpInfo.DEFAULT_ALGORITHM);

                OtpInfo otp;
                String tokenType = JsonUtils.optString(info, "tokenType");
                if (tokenType == null || tokenType.equals("TOTP")) {
                    int period = info.optInt("period", TotpInfo.DEFAULT_PERIOD);
                    otp = new TotpInfo(secret, algorithm, digits, period);
                } else if (tokenType.equals("HOTP")) {
                    long counter = info.optLong("counter", 0);
                    otp = new HotpInfo(secret, algorithm, digits, counter);
                } else if (tokenType.equals("STEAM")) {
                    int period = info.optInt("period", TotpInfo.DEFAULT_PERIOD);
                    otp = new SteamInfo(secret, algorithm, digits, period);
                } else {
                    throw new DatabaseImporterEntryException(String.format("Unrecognized tokenType: %s", tokenType), obj.toString());
                }

                return new VaultEntry(otp, name, issuer);
            } catch (OtpInfoException | JSONException | EncodingException e) {
                throw new DatabaseImporterEntryException(e, obj.toString());
            }
        }
    }
}

View on GitHub (pinned to d6f4e5925a)