{"record":{"id":"7240864b4eb6e7c6","repo":"beemdevelopment/Aegis","slug":"parameter-secret-is-not-present","errorCode":null,"errorMessage":"Parameter 'secret' is not present","messagePattern":"Parameter 'secret' is not present","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/src/main/java/com/beemdevelopment/aegis/otp/GoogleAuthInfo.java","lineNumber":53,"sourceCode":"\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 {\n            secret = (scheme.equals(MotpInfo.SCHEME)) ? Hex.decode(encodedSecret) : parseSecret(encodedSecret);\n        } catch (EncodingException e) {\n            throw new GoogleAuthInfoException(uri, \"Bad secret\", e);\n        }\n        if (secret.length == 0) {\n            throw new GoogleAuthInfoException(uri, \"Secret is empty\");\n        }\n\n        OtpInfo info;\n        String issuer = \"\";\n        try {\n            String type = (scheme.equals(MotpInfo.SCHEME)) ? MotpInfo.ID : uri.getHost();\n            if (type == null) {\n                throw new GoogleAuthInfoException(uri, String.format(\"Host not present in URI: %s\", uri.toString()));","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/app/src/main/java/com/beemdevelopment/aegis/otp/GoogleAuthInfo.java#L35-L71","documentation":"The otpauth:// URI parsed successfully and had a valid scheme, but the required 'secret' query parameter is missing. Every OTP URI must carry the shared secret; without it no authenticator can be constructed.","triggerScenarios":"parseUri(Uri) encountering a URI like otpauth://totp/label?issuer=X with no secret= parameter.","commonSituations":"Hand-crafted otpauth URIs missing the secret, provider exports that put the secret elsewhere, or QR generators that omit the parameter.","solutions":["Regenerate the otpauth URI including the secret query parameter (Base32 for totp/hotp, hex for motp)","Check the importing service's URI construction/documentation","Catch GoogleAuthInfoException and report the URI as incomplete to the user"],"exampleFix":"// before\nString uri = \"otpauth://totp/Example:alice?issuer=Example\";\n// after\nString uri = \"otpauth://totp/Example:alice?issuer=Example&secret=JBSWY3DPEHPK3PXP\";","handlingStrategy":"validation","validationCode":"if (uri.getQueryParameter(\"secret\") == null) throw new IllegalArgumentException(\"URI missing secret parameter\");","typeGuard":null,"tryCatchPattern":"try { return GoogleAuthInfo.parseUri(uri); } catch (GoogleAuthInfoException e) { promptForMissingSecret(); return null; }","preventionTips":["Always include secret= when generating otpauth URIs","Test generated URIs against a parser before distribution","Validate all required query params (secret, and counter for hotp) before import"],"tags":["android","otp","missing-parameter","uri"],"backgroundTag":"missing-required-argument","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"}