beemdevelopment/Aegis · error

Bad URI format

Error message

Bad URI format: %s

What it means

Thrown by GoogleAuthInfo.parseUri(String) when android.net.Uri.parse returns null for the supplied string, meaning the string is not a parseable URI. The library wraps it in a GoogleAuthInfoException including the original string.

Solutions

  1. Verify the input string is a complete URI (starts with a scheme like otpauth://) before calling parseUri
  2. Catch GoogleAuthInfoException and surface a user-friendly 'invalid QR code / URI' message
  3. Log the offending string (sanitized) to identify where the malformed input originates

Example fix

// before
GoogleAuthInfo info = GoogleAuthInfo.parseUri(rawText);
// after
if (rawText != null && rawText.startsWith("otpauth://")) {
    GoogleAuthInfo info = GoogleAuthInfo.parseUri(rawText);
} else {
    throw new GoogleAuthInfoException(null, "Not an otpauth URI");
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (s == null || !s.contains("://")) throw new IllegalArgumentException("not a URI");

Type guard

boolean isParseableUri(String s) { return s != null && android.net.Uri.parse(s) != null; }

Try / catch

try { GoogleAuthInfo info = GoogleAuthInfo.parseUri(s); } catch (GoogleAuthInfoException e) { showInvalidQrError(); }

Prevention

When it happens

Trigger: Calling GoogleAuthInfo.parseUri(s) with a null/unparseable string s such that Uri.parse(s) yields null.

Common situations: Scanning a corrupted QR code, passing a trimmed/empty string from a text field, or passing a Base32 secret directly instead of a full otpauth:// URI.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


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

Appendix: source

Thrown at app/src/main/java/com/beemdevelopment/aegis/otp/GoogleAuthInfo.java:39

public class GoogleAuthInfo implements Transferable, Serializable {
    public static final String SCHEME = "otpauth";
    public static final String SCHEME_EXPORT = "otpauth-migration";

    private OtpInfo _info;
    private String _accountName;
    private String _issuer;

    public GoogleAuthInfo(OtpInfo info, String accountName, String issuer) {
        _info = info;
        _accountName = accountName;
        _issuer = issuer;
    }

    public static GoogleAuthInfo parseUri(String s) throws GoogleAuthInfoException {
        Uri uri = Uri.parse(s);
        if (uri == null) {
            throw new GoogleAuthInfoException(uri, String.format("Bad URI format: %s", s));
        }
        return GoogleAuthInfo.parseUri(uri);
    }

    public static GoogleAuthInfo parseUri(Uri uri) throws GoogleAuthInfoException {
        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 {

View on GitHub (pinned to d6f4e5925a)