{"record":{"id":"4007d13a48e7d79c","repo":"passbolt/passbolt_api","slug":"mfa-setting-otp-provisioning-uri-is-not-set","errorCode":null,"errorMessage":"MFA setting OTP provisioning uri is not set.","messagePattern":"MFA setting OTP provisioning uri is not set\\.","errorType":"exception","errorClass":"RecordNotFoundException","httpStatus":404,"severity":"error","filePath":"plugins/PassboltCe/MultiFactorAuthentication/src/Utility/MfaAccountSettingsTotpTrait.php","lineNumber":32,"sourceCode":" * @link          https://www.passbolt.com Passbolt(tm)\n * @since         2.5.0\n */\nnamespace Passbolt\\MultiFactorAuthentication\\Utility;\n\nuse Cake\\Datasource\\Exception\\RecordNotFoundException;\n\ntrait MfaAccountSettingsTotpTrait\n{\n    /**\n     * Return OTP provisioning url\n     *\n     * @throws \\Cake\\Datasource\\Exception\\RecordNotFoundException if URI is not set\n     * @return string\n     */\n    public function getOtpProvisioningUri(): string\n    {\n        if (!isset($this->settings[MfaSettings::PROVIDER_TOTP][MfaAccountSettings::OTP_PROVISIONING_URI])) {\n            throw new RecordNotFoundException(__('MFA setting OTP provisioning uri is not set.'));\n        }\n\n        return $this->settings[MfaSettings::PROVIDER_TOTP][MfaAccountSettings::OTP_PROVISIONING_URI];\n    }\n\n    /**\n     * Return true if otp provisioning uri is set\n     *\n     * @return bool\n     */\n    public function isOtpProvisioningUriSet(): bool\n    {\n        return isset($this->settings[MfaSettings::PROVIDER_TOTP][MfaAccountSettings::OTP_PROVISIONING_URI]);\n    }\n}\n","sourceCodeStart":14,"sourceCodeEnd":48,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltCe/MultiFactorAuthentication/src/Utility/MfaAccountSettingsTotpTrait.php#L14-L48","documentation":"getOtpProvisioningUri() (MfaAccountSettingsTotpTrait) returns the stored TOTP provisioning URI. It throws RecordNotFoundException when settings['totp']['otpProvisioningUri'] is not set, i.e. TOTP was never configured for the account or the URI was never persisted.","triggerScenarios":"Calling getOtpProvisioningUri() on account settings where the totp provider entry lacks the OTP_PROVISIONING_URI key — before TOTP setup completes or after settings saved without the URI.","commonSituations":"Rendering the QR code page for a user whose TOTP enrollment was interrupted; reading settings from a store where the URI key was stripped; calling it for users who use yubikey instead of totp; tests constructing partial settings arrays.","solutions":["Ensure TOTP setup completed via MfaForm/verify flow, which persists the provisioning URI before it is read.","Check isset($this->settings['totp']['otpProvisioningUri']) before calling, or expose an has method.","Catch RecordNotFoundException and redirect the user to (re)start TOTP enrollment.","If enrolling a user who already has TOTP, regenerate the provisioning URI via the TOTP setup service instead of reading stale settings."],"exampleFix":"// before\n$uri = $mfaAccountSettings->getOtpProvisioningUri();\n// after\ntry {\n    $uri = $mfaAccountSettings->getOtpProvisioningUri();\n} catch (\\Cake\\Datasource\\Exception\\RecordNotFoundException $e) {\n    return $this->redirect(['action' => 'setupTotp']); // restart enrollment\n}","handlingStrategy":"try-catch","validationCode":"$uri = null;\ntry { $uri = $s->getOtpProvisioningUri(); } catch (RecordNotFoundException $e) {}","typeGuard":null,"tryCatchPattern":"try { $uri = $s->getOtpProvisioningUri(); } catch (\\Cake\\Datasource\\Exception\\RecordNotFoundException $e) { return redirect to TOTP setup; }","preventionTips":["Complete the TOTP verify flow before rendering QR/provisioning screens","Never assume totp settings exist for users enrolled in other providers","Persist the provisioning URI atomically with the totp provider entry"],"tags":["mfa","totp","record-not-found"],"backgroundTag":"record-not-found","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"}