{"record":{"id":"5a57445c5c97a04b","repo":"passbolt/passbolt_api","slug":"could-not-generate-totp-secret-please-try-again-later","errorCode":null,"errorMessage":"Could not generate TOTP secret, please try again later.","messagePattern":"Could not generate TOTP secret, please try again later\\.","errorType":"http","errorClass":"InternalErrorException","httpStatus":500,"severity":"error","filePath":"plugins/PassboltCe/MultiFactorAuthentication/src/Utility/MfaOtpFactory.php","lineNumber":70,"sourceCode":"        $url = str_replace(':', '', $url);\n        $url = rtrim($url, '/');\n\n        return $url;\n    }\n\n    /**\n     * Generate a random TOTP\n     *\n     * @param \\App\\Utility\\UserAccessControl $uac user access control\n     * @return string provisioning uri\n     */\n    public static function generateTOTP(UserAccessControl $uac): string\n    {\n        $secretLength = self::getAndSanitizeSecretLengthFromConfig();\n        try {\n            $secret = trim(Base32::encode(random_bytes($secretLength)), '='); // some random bytes Base32 without padding\n        } catch (TypeError $exception) {\n            throw new InternalErrorException(\n                'Could not generate TOTP secret, please try again later.',\n                500,\n                $exception\n            );\n        } catch (Exception $exception) {\n            throw new InternalErrorException(\n                'Could not generate enough random bytes, please try again later.',\n                500,\n                $exception\n            );\n        }\n\n        $totp = TOTP::create($secret);\n        $totp->setLabel($uac->getUsername()); // label: string shown below the code digits\n        $totp->setIssuer(self::getIssuer()); // issuer: string shown above the code digits\n\n        return $totp->getProvisioningUri();\n    }","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltCe/MultiFactorAuthentication/src/Utility/MfaOtpFactory.php#L52-L88","documentation":"Wraps a TypeError thrown while generating a random TOTP secret into an InternalErrorException. The TypeError comes from random_bytes receiving an invalid secret length (e.g. non-integer or negative) derived from the MFA config.","triggerScenarios":"Calling MfaOtpFactory::generateTOTP when the configured TOTP secret length resolves to an invalid value, causing random_bytes($secretLength) to raise TypeError (PHP 8 throws TypeError for bad lengths).","commonSituations":"A malformed passbolt.php or config/mfa.php entry like 'secretLength' => '5' (string) or a negative number instead of a positive integer.","solutions":["Inspect the MFA TOTP configuration value used for secret length and set it to a valid positive integer.","Clear the config cache (bin/cake cache clear_all) after fixing the config file.","Check for plugins or custom code overriding MfaOtpFactory::getAndSanitizeSecretLengthFromConfig.","Retry TOTP setup once config is fixed; if persistent, check the PHP version behavior of random_bytes."],"exampleFix":"// before (config/mfa.php)\n'totp' => ['secretLength' => 'five'],\n// after\n'totp' => ['secretLength' => 32],","handlingStrategy":"validation","validationCode":"if (!is_int($secretLength) || $secretLength <= 0) { throw new \\InvalidArgumentException('secretLength must be a positive int'); }","typeGuard":"function isValidSecretLength($v): bool { return is_int($v) && $v > 0; }","tryCatchPattern":"try { $secret = MfaOtpFactory::generateTOTP($uac); } catch (InternalErrorException $e) { // inspect TOTP secretLength config }","preventionTips":["Keep secretLength as a positive integer in config/mfa.php.","Clear config cache after editing config files.","Avoid overriding MfaOtpFactory config keys from plugins without type checks."],"tags":["mfa","totp","config","random-bytes"],"backgroundTag":"invalid-config-value","analyzedSha":"31c1bbc10f32808a607fa9bd81891e898779c0bc","analyzedAt":"2026-09-17T00:04:38.960Z","contentChangedAt":"2026-09-17T00:04:38.960Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}