passbolt/passbolt_api · error · FormValidationException

Could not validate the data.

Error message

Could not validate the data.

What it means

update() expects payload data shaped [modified:<datetime>, data:<string>] validated by MetadataSessionKeyUpdateForm. If the form fails to execute, a FormValidationException with message 'Could not validate the data.' is thrown (400).

Solutions

  1. Send both fields: modified as ISO-8601 datetime and data as string
  2. Read the form's errors from the exception/response to see the exact failing field
  3. Match the payload schema used by the official passbolt clients

Example fix

// before
$service->update($uac, $id, ['data' => $armored]);
// after
$service->update($uac, $id, ['data' => $armored, 'modified' => $key->modified->format('Y-m-d\TH:i:sP')]);
Defensive patterns

Strategy: validation

Validate before calling

$errors = []; if (!isset($data['data']) || !is_string($data['data'])) { $errors[] = 'data must be a string'; } if (!isset($data['modified']) || strtotime($data['modified']) === false) { $errors[] = 'modified must be a datetime'; }

Type guard

function isValidUpdatePayload(array $d): bool { return isset($d['data'], $d['modified']) && is_string($d['data']) && strtotime($d['modified']) !== false; }

Try / catch

try { $service->update($uac, $id, $data); } catch (FormValidationException $e) { $errors = $e->getForm()->getErrors(); }

Prevention

When it happens

Trigger: Missing 'modified' or 'data' fields, 'modified' not a valid datetime, 'data' not a string / failing OpenPGP-related validation, or extra malformed payload.

Common situations: Client sends only {'data': ...} without modified, datetime format mismatch (timezone/locale), sending base64 or JSON where the form expects a string, API version drift in payload shape.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

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

     * @param \App\Utility\UserAccessControl $uac UAC.
     * @param string $id The metadata session key identifier.
     * @param array $data non-empty array of user provided data
     * @throws \Cake\Http\Exception\BadRequestException
     * @throws \Cake\Http\Exception\NotFoundException
     * @throws \Cake\Http\Exception\ConflictException
     * @throws \App\Error\Exception\CustomValidationException
     * @return \Passbolt\Metadata\Model\Entity\MetadataSessionKey
     */
    public function update(UserAccessControl $uac, string $id, array $data): MetadataSessionKey
    {
        if (!Validation::uuid($id)) {
            throw new BadRequestException(__('The metadata session key identifier should be a UUID.'));
        }

        // 400 invalid user provided data, we expect [modified:<datetime>, data:<string>]
        $form = new MetadataSessionKeyUpdateForm();
        if (!$form->execute($data)) {
            throw new FormValidationException(__('Could not validate the data.'), $form);
        }
        $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

View on GitHub (pinned to 31c1bbc10f)