passbolt/passbolt_api · info · BadRequestException

The metadata session key data is identical.

Error message

The metadata session key data is identical.

What it means

No-op guard in MetadataSessionKeyUpdateService::update(): the submitted session key data is byte-identical to the stored record, so the update would change nothing and a conflict is raised rather than performing a redundant write.

Solutions

  1. Compute the new payload only when the underlying key/plaintext changed
  2. Check the existing value before calling update and skip if identical
  3. Treat this 400 as a no-op success in idempotent pipelines

Example fix

// before
$service->update($uac, $id, ['data' => $same, 'modified' => $modified]);
// after
if ($same !== $existing->get('data')) { $service->update($uac, $id, ['data' => $same, 'modified' => $modified]); }
Defensive patterns

Strategy: validation

Validate before calling

if ($newData === $existingKey->get('data')) { return; } // skip no-op update

Try / catch

try { $service->update($uac, $id, $data); } catch (BadRequestException $e) { /* identical data: treat as no-op */ }

Prevention

When it happens

Trigger: Client re-sends the same encrypted payload without modification, or retries an already-applied update with identical content.

Common situations: Idempotent retry logic re-POSTing the same body, cron jobs refreshing keys unconditionally, generating the same armored message from unchanged plaintext.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17). Data as JSON: /api/errors/f33543627963a667. Report an issue: GitHub.

Appendix: source

Thrown at plugins/PassboltCe/Metadata/src/Service/MetadataSessionKeyUpdateService.php:80

        $data = $form->getData();

        /** @var \Passbolt\Metadata\Model\Table\MetadataSessionKeysTable $metadataSessionKeysTable */
        $metadataSessionKeysTable = $this->fetchTable('Passbolt/Metadata.MetadataSessionKeys');

        try {
            /** @var \Passbolt\Metadata\Model\Entity\MetadataSessionKey $metadataSessionKey */
            $metadataSessionKey = $metadataSessionKeysTable
                ->find()
                ->where(['id' => $id, 'user_id' => $uac->getId()])
                ->firstOrFail();
        } catch (RecordNotFoundException $e) {
            // 404 session key entry does not exist or not for current user_id
            throw new NotFoundException(__('The metadata session key does not exist or does not belong to this user.'));
        }

        // 400 no changes to be made
        if ($data['data'] === $metadataSessionKey->get('data')) {
            throw new BadRequestException(__('The metadata session key data is identical.'));
        }
        // 409 if the modified date is not equal to the persisted session key one
        $asserTime = (new DateTime($data['modified']))->diffInSeconds($metadataSessionKey->get('modified')) === 0;
        if (!$asserTime) {
            throw new ConflictException(__('The metadata session key data has changed.'));
        }

        $metadataSessionKey = $metadataSessionKeysTable->patchEntity(
            $metadataSessionKey,
            ['data' => $data['data']],
            ['accessibleFields' => ['data' => true]]
        );

        try {
            /** @var \Passbolt\Metadata\Model\Entity\MetadataSessionKey $updatedEntity */
            $updatedEntity = $metadataSessionKeysTable->saveOrFail($metadataSessionKey);
        } catch (PersistenceFailedException $exception) { // @phpstan-ignore-line
            // 400 openpgp data does not validate, for example it's not for the current user

View on GitHub (pinned to 31c1bbc10f)