{"record":{"id":"24f186b81c012b75","repo":"beemdevelopment/Aegis","slug":"bad-uri-format-s","errorCode":null,"errorMessage":"Bad URI format: %s","messagePattern":"Bad URI format: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/src/main/java/com/beemdevelopment/aegis/otp/GoogleAuthInfo.java","lineNumber":39,"sourceCode":"\npublic class GoogleAuthInfo implements Transferable, Serializable {\n    public static final String SCHEME = \"otpauth\";\n    public static final String SCHEME_EXPORT = \"otpauth-migration\";\n\n    private OtpInfo _info;\n    private String _accountName;\n    private String _issuer;\n\n    public GoogleAuthInfo(OtpInfo info, String accountName, String issuer) {\n        _info = info;\n        _accountName = accountName;\n        _issuer = issuer;\n    }\n\n    public static GoogleAuthInfo parseUri(String s) throws GoogleAuthInfoException {\n        Uri uri = Uri.parse(s);\n        if (uri == null) {\n            throw new GoogleAuthInfoException(uri, String.format(\"Bad URI format: %s\", s));\n        }\n        return GoogleAuthInfo.parseUri(uri);\n    }\n\n    public static GoogleAuthInfo parseUri(Uri uri) throws GoogleAuthInfoException {\n        String scheme = uri.getScheme();\n        if (scheme == null || !(scheme.equals(SCHEME) || scheme.equals(MotpInfo.SCHEME))) {\n            throw new GoogleAuthInfoException(uri, String.format(\"Unsupported protocol: %s\", scheme));\n        }\n\n        // 'secret' is a required parameter\n        String encodedSecret = uri.getQueryParameter(\"secret\");\n        if (encodedSecret == null) {\n            throw new GoogleAuthInfoException(uri, \"Parameter 'secret' is not present\");\n        }\n\n        byte[] secret;\n        try {","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/app/src/main/java/com/beemdevelopment/aegis/otp/GoogleAuthInfo.java#L21-L57","documentation":"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.","triggerScenarios":"Calling GoogleAuthInfo.parseUri(s) with a null/unparseable string s such that Uri.parse(s) yields null.","commonSituations":"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.","solutions":["Verify the input string is a complete URI (starts with a scheme like otpauth://) before calling parseUri","Catch GoogleAuthInfoException and surface a user-friendly 'invalid QR code / URI' message","Log the offending string (sanitized) to identify where the malformed input originates"],"exampleFix":"// before\nGoogleAuthInfo info = GoogleAuthInfo.parseUri(rawText);\n// after\nif (rawText != null && rawText.startsWith(\"otpauth://\")) {\n    GoogleAuthInfo info = GoogleAuthInfo.parseUri(rawText);\n} else {\n    throw new GoogleAuthInfoException(null, \"Not an otpauth URI\");\n}","handlingStrategy":"try-catch","validationCode":"if (s == null || !s.contains(\"://\")) throw new IllegalArgumentException(\"not a URI\");","typeGuard":"boolean isParseableUri(String s) { return s != null && android.net.Uri.parse(s) != null; }","tryCatchPattern":"try { GoogleAuthInfo info = GoogleAuthInfo.parseUri(s); } catch (GoogleAuthInfoException e) { showInvalidQrError(); }","preventionTips":["Validate the scanned/entered text starts with a scheme before parsing","Never pass raw Base32 secrets to parseUri","Catch GoogleAuthInfoException at all import entry points"],"tags":["android","otp","uri-parsing","input-validation"],"backgroundTag":"invalid-url-format","analyzedSha":"d6f4e5925a97e4e91593f1542085eae03432a759","analyzedAt":"2026-09-08T00:46:31.111Z","contentChangedAt":"2026-09-08T00:46:31.111Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}