{"record":{"id":"74ee78206a3e74a6","repo":"passbolt/passbolt_api","slug":"mfa-verification-date-is-not-set-for-this-provider","errorCode":null,"errorMessage":"MFA verification date is not set for this provider.","messagePattern":"MFA verification date is not set for this provider\\.","errorType":"exception","errorClass":"RecordNotFoundException","httpStatus":404,"severity":"error","filePath":"plugins/PassboltCe/MultiFactorAuthentication/src/Utility/MfaAccountSettings.php","lineNumber":175,"sourceCode":"        foreach ($providers as $provider) {\n            if ($this->isProviderReady($provider)) {\n                $result[] = $provider;\n            }\n        }\n\n        return $result;\n    }\n\n    /**\n     * Return verification date time as FrozenTime\n     *\n     * @param string $provider name of the provider\n     * @return \\Cake\\I18n\\DateTime\n     */\n    public function getVerifiedFrozenTime(string $provider): DateTime\n    {\n        if (!isset($this->settings[$provider][self::VERIFIED])) {\n            throw new RecordNotFoundException(__('MFA verification date is not set for this provider.'));\n        }\n\n        return new DateTime($this->settings[$provider][MfaAccountSettings::VERIFIED]);\n    }\n\n    /**\n     * Enable a new mfa provider for the given user\n     *\n     * @param \\App\\Utility\\UserAccessControl $uac access control\n     * @param string $provider name of the provider\n     * @param array|null $data data\n     * @return void\n     */\n    public static function enableProvider(UserAccessControl $uac, string $provider, ?array $data = []): void\n    {\n        $data['verified'] = DateTime::now();\n        try {\n            /** @var \\Passbolt\\AccountSettings\\Model\\Table\\AccountSettingsTable $AccountSettings */","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltCe/MultiFactorAuthentication/src/Utility/MfaAccountSettings.php#L157-L193","documentation":"getVerifiedFrozenTime() returns the DateTime at which a given provider was verified for the account. It throws RecordNotFoundException when settings[provider][VERIFIED] is absent — the provider exists (or not) but no verification timestamp was recorded for it.","triggerScenarios":"Calling getVerifiedFrozenTime($provider) with a provider that has no 'verified' entry in the account settings — e.g. provider configured but never successfully verified, or provider key entirely missing from settings.","commonSituations":"Checking verification expiry for a provider the user enabled but never completed verification for; race between enabling a provider and verifying it; asking about a provider the user never set up; querying org-disabled providers against stale account settings.","solutions":["Verify the provider is both enabled and verified before querying: check isset($settings[$provider]['verified']) via an accessor or the verify() flow first.","Catch RecordNotFoundException and treat the provider as unverified.","Have the user complete the MFA verification flow for that provider so the verified timestamp is stored.","Confirm the provider name string matches the enabled provider exactly (totp, yubikey, duo)."],"exampleFix":"// before\n$verifiedAt = $mfaAccountSettings->getVerifiedFrozenTime('totp');\n// after\ntry {\n    $verifiedAt = $mfaAccountSettings->getVerifiedFrozenTime('totp');\n} catch (\\Cake\\Datasource\\Exception\\RecordNotFoundException $e) {\n    $verifiedAt = null; // provider not verified\n}","handlingStrategy":"try-catch","validationCode":"$verifiedAt = null;\ntry { $verifiedAt = $s->getVerifiedFrozenTime($provider); } catch (RecordNotFoundException $e) {}","typeGuard":null,"tryCatchPattern":"try { $dt = $s->getVerifiedFrozenTime($p); } catch (\\Cake\\Datasource\\Exception\\RecordNotFoundException $e) { $dt = null; } // treat as unverified","preventionTips":["Only query verification date for providers confirmed enabled","Route unverified providers back through the verify flow instead of reading the timestamp","Use the verify()/isVerified helpers rather than raw timestamp access where possible"],"tags":["mfa","record-not-found","verification"],"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-21T09:17:21.228Z"}