beemdevelopment/Aegis · error · GoogleAuthInfoException

Empty secret (empty authority)

Error message

Empty secret (empty authority)

What it means

The Bitwarden importer handles Bitwarden's special "steam://" URIs, where the TOTP secret is carried in the URI authority. If a steam URI has no authority component (empty secret), GoogleAuthInfoException is thrown since a Steam TOTP entry cannot exist without a secret.

Solutions

  1. Open the item in Bitwarden and fill in the correct Steam TOTP secret, then re-export
  2. Fix the URI in the export so the secret appears in the authority: steam://BASE32SECRET
  3. Remove or skip entries with empty secrets during import
  4. Verify the seed is valid Base32 after editing

Example fix

// before
String secretString = uri.getAuthority();
if (secretString == null) {
    throw new GoogleAuthInfoException(uri, "Empty secret (empty authority)");
}
// after
String secretString = uri.getAuthority();
if (secretString == null || secretString.isEmpty()) {
    throw new GoogleAuthInfoException(uri, "Empty secret (empty authority): steam URIs must be steam://<base32secret>");
}
Defensive patterns

Strategy: validation

Validate before calling

Uri uri = Uri.parse(s);
if ("steam".equals(uri.getScheme()) && (uri.getAuthority() == null || uri.getAuthority().isEmpty())) {
    throw new IllegalArgumentException("steam:// URI missing base32 secret in authority");
}

Type guard

static boolean hasSteamSecret(Uri uri) {
    return !"steam".equals(uri.getScheme())
        || (uri.getAuthority() != null && !uri.getAuthority().isEmpty());
}

Try / catch

try {
    info = GoogleAuthInfo.parseUri(s);
} catch (GoogleAuthInfoException e) {
    if (e.getMessage().contains("Empty secret")) {
        skipEntry(uri, "missing Steam seed");
    }
}

Prevention

When it happens

Trigger: Importing a Bitwarden export whose otp:// (steam) URI looks like "steam://" or "steam://?..." with no secret before the query string — i.e. the item's TOTP seed was empty or malformed.

Common situations: Bitwarden vault item with an empty/invalid TOTP custom field; hand-crafted URI missing the secret; copy-paste truncation of the seed before saving in Bitwarden.

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


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

Appendix: source

Thrown at app/src/main/java/com/beemdevelopment/aegis/importers/BitwardenImporter.java:119

            return result;
        }

        private static VaultEntry convertEntry(String obj) throws DatabaseImporterEntryException {
            try {
                GoogleAuthInfo info = BitwardenImporter.parseUri(obj);
                return new VaultEntry(info);
            } catch (GoogleAuthInfoException | EncodingException | OtpInfoException | URISyntaxException e) {
                throw new DatabaseImporterEntryException(e, obj);
            }
        }
    }

    private static GoogleAuthInfo parseUri(String s) throws EncodingException, OtpInfoException, URISyntaxException, GoogleAuthInfoException {
        Uri uri = Uri.parse(s);
        if (Objects.equals(uri.getScheme(), "steam")) {
            String secretString = uri.getAuthority();
            if (secretString == null) {
                throw new GoogleAuthInfoException(uri, "Empty secret (empty authority)");
            }
            byte[] secret = Base32.decode(secretString);
            return new GoogleAuthInfo(new SteamInfo(secret), "Steam account", "Steam");
        }

        return GoogleAuthInfo.parseUri(uri);
    }
}

View on GitHub (pinned to d6f4e5925a)