flarum/framework · error · ValidationException

Incorrect password

Error message

Incorrect password

What it means

When a user confirms their own GDPR erasure request, the endpoint requires the account password; if checkPassword fails (or meta.password is absent) a ValidationException with field 'password' and message 'Incorrect password' is thrown in the ErasureRequestResource endpoint's before hook. Users created via third-party OAuth (no password) bypass the check.

Solutions

  1. Enter the correct password of the account in the meta.password field of the request body.
  2. If the password is forgotten, reset it first, then retry the erasure confirmation.
  3. For OAuth-only accounts no password is required — the check is skipped automatically; confirm the account actually has no login providers if you expected a bypass.
  4. Inspect the request payload to confirm meta.password is present and non-empty.

Example fix

// before
{ "meta": {} }
// after
{ "meta": { "password": "current-account-password" } }
Defensive patterns

Strategy: validation

Validate before calling

if ($actor->loginProviders()->count() === 0 && empty($body['meta']['password'])) { /* require password input in the UI first */ }

Try / catch

try { await api.confirmErasure(id, { meta: { password } }); } catch (e) { if (e.status === 422) showPasswordError(); }

Prevention

When it happens

Trigger: POST/PATCH on the erasure request resource (self-confirmation flow) where body meta.password is missing, empty, or does not match the actor's stored password hash.

Common situations: Frontend form not sending meta.password; user typo; user's password changed elsewhere; users migrated from other providers without password hashes.

Related errors


AI-assisted analysis of flarum/framework@4b939f6853 (2026-09-15). Data as JSON: /api/errors/1b0d247014fe1e91. Report an issue: GitHub.

Appendix: source

Thrown at extensions/gdpr/src/Api/Resource/ErasureRequestResource.php:98

                'user_id' => $context->getActor()->id,
            ]);
        }

        return parent::newModel($context);
    }

    public function endpoints(): array
    {
        return [
            Endpoint\Create::make()
                ->authenticated()
                ->before(function (Context $context) {
                    $actor = $context->getActor();

                    // If they signed up using a third party oauth provider, they won't have a password
                    // so we can't check it. We'll just assume they're authenticated.
                    if ($actor->loginProviders()->count() === 0 && ! $actor->checkPassword(Arr::get($context->body(), 'meta.password', ''))) {
                        throw new ValidationException(['password' => 'Incorrect password']);
                    }
                }),
            Endpoint\Update::make()
                ->can('process'),
            Endpoint\Endpoint::make('cancel')
                ->route('POST', '{id}/cancel')
                ->authenticated()
                ->can('cancel')
                ->action(function (Context $context) {
                    /** @var ErasureRequest $request */
                    $request = $context->model;

                    $request->cancelled_at = Carbon::now();
                    $request->status = ErasureRequest::STATUS_CANCELLED;
                    $request->user_confirmed_at = null;
                    $request->verification_token = null;
                    $request->save();

View on GitHub (pinned to 4b939f6853)