passbolt/passbolt_api · error · Cake\Http\Exception\BadRequestException

Resource metadata key type is invalid.

Error message

Resource metadata key type is invalid.

What it means

Thrown by ShareController::_assertRequestParameters during v5 (metadata) validation: the resource is v5-format and its metadata_key_type is 'user_key', which is invalid for sharing — v5 resources must be encrypted with a shared metadata key, not a per-user key.

Solutions

  1. Re-encrypt the resource metadata with the proper shared metadata key (metadata key type) before sharing.
  2. Upgrade all clients to a version that writes correct v5 metadata_key_type.
  3. If the data is corrupt from migration, use the metadata keys maintenance/rotate tooling to fix the record.

Example fix

// before (resource.metadata_key_type === 'user_key')
await api.put(`/share/resource/${id}`, perms);
// after
await rotateMetadataKey([id]); // re-encrypt metadata with shared metadata key
await api.put(`/share/resource/${id}`, perms);
Defensive patterns

Strategy: validation

Validate before calling

if (resource.contentType?.startsWith('v5') && resource.metadata_key_type === 'user_key') {
  throw new Error('resource metadata must use shared metadata key, not user_key');
}

Type guard

function hasValidV5Metadata(r) { return !r.metadata_key_type || r.metadata_key_type !== 'user_key'; }

Try / catch

try { await share(id, perms); } catch (e) { if (e.status === 400 && /metadata key type/.test(e.message)) { await reEncryptMetadata([id]); } else throw e; }

Prevention

When it happens

Trigger: Sharing a v5 resource whose metadata was created with metadata_key_type='user_key' (legacy/incorrect encryption), typically data produced before metadata keys were fully rolled out or by a misconfigured client.

Common situations: Migrated v4→v5 data with wrong metadata_key_type; mixing client versions where one wrote user-key metadata; environments testing metadata key rotation.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at src/Controller/Share/ShareController.php:150

        try {
            $resource = $this->Resources->get($resourceId);
        } catch (RecordNotFoundException $e) {
            throw new NotFoundException(__('The resource does not exist.'));
        }
        // The resource is not soft deleted.
        if ($resource->deleted) {
            throw new NotFoundException(__('The resource does not exist.'));
        }
        // The user can access the resource.
        $acoType = PermissionsTable::RESOURCE_ACO;
        $userId = $this->User->id();
        if (!$this->Resources->Permissions->hasAccess($acoType, $resourceId, $userId, Permission::OWNER)) {
            throw new ForbiddenException(__('You are not authorized to share this resource.'));
        }
        // V5 validations
        $resourceDto = MetadataResourceDto::fromArray($resource->toArray());
        if ($resourceDto->isV5() && $resource->get('metadata_key_type') === 'user_key') {
            throw new BadRequestException(__('Resource metadata key type is invalid.'));
        }
    }

    /**
     * Format the result.
     *
     * This entry point is used by the plugin app, and due to the V1 legacy the output body must be
     * formatted as following:
     *
     * [
     *   'changes' => [
     *     'added' => [
     *       ['User' => ['id' => uuid]],
     *       ...
     *     ],
     *     'removed' => [
     *       ['User' => ['id' => uuid]],
     *       ...

View on GitHub (pinned to 31c1bbc10f)