passbolt/passbolt_api · error · BadRequestException
V4 related fields are not supported for V5.
Error message
V4 related fields are not supported for V5.
What it means
MetadataResourceDto::validateRequestPayload rejects resource payloads that mix v5 metadata fields with non-null v4 cleartext fields (name, username, uri, description). Once the payload is identified as v5, any of those legacy fields present triggers this BadRequestException. It enforces that v5 resources carry only encrypted metadata, not both formats.
Solutions
- Move the cleartext fields (name, username, uri, description) inside the encrypted `metadata` blob and remove them from the top-level payload.
- Send either a pure v4 payload (only name/username/uri/description) or a pure v5 payload (only metadata/metadata_key_id/metadata_key_type).
- Upgrade the client/SDK to build v5 metadata: encrypt the cleartext object (object_type PASSBOLT_RESOURCE_METADATA) with the metadata key.
- If v5 usage is unintended, drop the metadata fields from the request so the DTO treats it as v4.
Example fix
// before
{"name": "GitHub", "username": "ops@acme", "metadata": "<encrypted>", "metadata_key_id": "<uuid>", "metadata_key_type": "shared_key"}
// after
{"metadata": "<encrypted blob containing name/username/uris/description>", "metadata_key_id": "<uuid>", "metadata_key_type": "shared_key"} Defensive patterns
Strategy: validation
Validate before calling
$v4Fields = ['name', 'username', 'uri', 'description'];
$isV5 = isset($payload['metadata']) && $payload['metadata'] !== null;
if ($isV5) {
foreach ($v4Fields as $f) {
if (array_key_exists($f, $payload) && $payload[$f] !== null) {
throw new InvalidArgumentException("v5 payload must not contain v4 field: $f");
}
}
} Type guard
function hasNoV4FieldsWithV5(array $p): bool {
if (!isset($p['metadata']) || $p['metadata'] === null) return true;
foreach (['name','username','uri','description'] as $f) {
if (array_key_exists($f, $p) && $p[$f] !== null) return false;
}
return true;
} Try / catch
try {
$dto = MetadataResourceDto::fromArray($payload);
} catch (BadRequestException $e) {
// move name/username/uri/description into the encrypted metadata blob and retry
} Prevention
- When migrating to v5, serialize cleartext props inside the encrypted metadata object only
- Strip legacy keys from payloads copied from v4 code paths
- Run a payload sanitizer that removes v4 keys when metadata is present
- Write integration tests covering both pure-v4 and pure-v5 request shapes
When it happens
Trigger: POST/PUT to resource endpoints with a payload containing metadata/metadata_key_id/metadata_key_type plus any of name, username, uri, or description (non-null), with the Metadata plugin enabled; constructing MetadataResourceDto::fromArray with mixed-format data.
Common situations: v4-era clients or scripts hitting a v5-enabled server and sending the full legacy resource object with metadata fields appended; integrations that copy a v4 resource and add a `metadata` key; incomplete SDK upgrades that still serialize description/username at the top level.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- V4 related fields are not supported for V5.
- Few fields are missing for the V5.
- The metadata private key data must be an array.
- An array of arrays is expected.
- The entity must be an array.
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/01da19bd915114be.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/PassboltCe/Metadata/src/Model/Dto/MetadataResourceDto.php:187
throw new BadRequestException($msg);
}
// Now that we know that we have a valid v5 payload, we check that no v4 fields are in the payload
$v4SuperfluousFields = [];
foreach (self::V4_META_PROPS as $v4Field) {
if (array_key_exists($v4Field, $payload) && !is_null($payload[$v4Field])) {
$v4SuperfluousFields[] = $v4Field;
}
}
if (!empty($v4SuperfluousFields)) {
$msg = __('V4 related fields are not supported for V5.');
if (Configure::read('debug')) {
Log::error($msg);
Log::error(__('Superfluous fields: {0}', implode(', ', $v4SuperfluousFields)));
}
throw new BadRequestException($msg);
}
}
/**
* Returns metadata array in cleartext form as per v5 format.
*
* @param bool $mapResourceType Should map resource type or not.
* @return array
*/
public function getClearTextMetadata(bool $mapResourceType = true): array
{
$resourceTypeId = $this->data[self::RESOURCE_TYPE_ID];
if ($mapResourceType) {
$mapping = ResourceType::getV5Mapping();
$v4resourceTypeId = $this->data[self::RESOURCE_TYPE_ID];
if (!isset($mapping[$v4resourceTypeId])) {
throw new InternalErrorException(__('No resource type mapping for ID \'{0}\'', $v4resourceTypeId));View on GitHub (pinned to 31c1bbc10f)