{"record":{"id":"d784f7558f80288e","repo":"passbolt/passbolt_api","slug":"few-fields-are-missing-for-the-v5-metadataresourcedto","errorCode":null,"errorMessage":"Few fields are missing for the V5.","messagePattern":"Few fields are missing for the V5\\.","errorType":"validation","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"plugins/PassboltCe/Metadata/src/Model/Dto/MetadataResourceDto.php","lineNumber":170,"sourceCode":"                $isV4 = false;\n            } else {\n                $v5MissingFields[] = $metadataField;\n            }\n        }\n        if ($isV4) {\n            return;\n        }\n\n        // Now that we know that we are in v5, we check that all the v5 metadata fields are set\n        // If all v5 fields are not provided, throw an exception.\n        if (!empty($v5MissingFields)) {\n            $msg = __('Few fields are missing for the V5.');\n            if (Configure::read('debug')) {\n                Log::error($msg);\n                Log::error(__('Missing fields: {0}', implode(', ', $v5MissingFields)));\n            }\n\n            throw new BadRequestException($msg);\n        }\n\n        // Now that we know that we have a valid v5 payload, we check that no v4 fields are in the payload\n        $v4SuperfluousFields = [];\n        foreach (self::V4_META_PROPS as $v4Field) {\n            if (array_key_exists($v4Field, $payload) && !is_null($payload[$v4Field])) {\n                $v4SuperfluousFields[] = $v4Field;\n            }\n        }\n        if (!empty($v4SuperfluousFields)) {\n            $msg = __('V4 related fields are not supported for V5.');\n            if (Configure::read('debug')) {\n                Log::error($msg);\n                Log::error(__('Superfluous fields: {0}', implode(', ', $v4SuperfluousFields)));\n            }\n\n            throw new BadRequestException($msg);\n        }","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltCe/Metadata/src/Model/Dto/MetadataResourceDto.php#L152-L188","documentation":"MetadataResourceDto::validateRequestPayload treats a resource payload as v5 when any of metadata, metadata_key_id, or metadata_key_type is present and non-null; it then requires ALL three v5 fields to be set. If any are missing/null it throws this BadRequestException. This enforces complete v5 encrypted-metadata payloads for resources.","triggerScenarios":"POST/PUT to resource endpoints (/resources.json, /resources/<id>.json) with a payload including e.g. `metadata` but missing `metadata_key_id` or `metadata_key_type` (or having them null), with the Metadata plugin enabled; MetadataResourceDto::fromArray with a partial v5 payload.","commonSituations":"Clients migrated halfway to v5 that send the encrypted `metadata` blob but forget the key id/type; payloads where metadata_key_id is explicitly set to null for user-key scenarios; copy-pasted request examples missing one field.","solutions":["Provide all three v5 fields in the payload: metadata, metadata_key_id, and metadata_key_type (all non-null).","Enable debug logging (Configure::write('debug', true)) — the server logs the exact list of missing fields — and add them.","If a v4 resource is intended, remove the v5 fields entirely so the payload falls back to the v4 path (name/username/uri/description).","Update the client/SDK to construct complete v5 payloads, encrypting the cleartext metadata before sending."],"exampleFix":"// before\n{\"metadata\": \"<encrypted>\", \"metadata_key_type\": \"shared_key\"}\n\n// after\n{\"metadata\": \"<encrypted>\", \"metadata_key_id\": \"<uuid>\", \"metadata_key_type\": \"shared_key\"}","handlingStrategy":"validation","validationCode":"$v5 = ['metadata', 'metadata_key_id', 'metadata_key_type'];\n$present = array_filter($v5, fn($f) => isset($payload[$f]) && $payload[$f] !== null);\nif (count($present) > 0 && count($present) < 3) {\n    throw new InvalidArgumentException('v5 payload incomplete: missing ' . implode(', ', array_diff($v5, array_keys($present))));\n}","typeGuard":"function isCompleteV5ResourcePayload(array $p): bool {\n    return isset($p['metadata'], $p['metadata_key_id'], $p['metadata_key_type'])\n        && $p['metadata'] !== null && $p['metadata_key_id'] !== null && $p['metadata_key_type'] !== null;\n}","tryCatchPattern":"try {\n    $dto = MetadataResourceDto::fromArray($payload);\n} catch (BadRequestException $e) {\n    // payload was partially v5: complete metadata_key_id/metadata_key_type or drop v5 fields\n}","preventionTips":["Build v5 payloads from a single helper that always emits all three v5 fields","Never send metadata_key_id: null explicitly — omit v5 fields entirely for v4","Read the server debug log ('Missing fields: ...') to identify exactly what is absent","Add contract tests asserting the v5 field trio is always present"],"tags":["passbolt","api","v5-metadata","missing-fields","bad-request"],"backgroundTag":"missing-required-argument","analyzedSha":"31c1bbc10f32808a607fa9bd81891e898779c0bc","analyzedAt":"2026-09-17T00:04:38.960Z","contentChangedAt":"2026-09-17T00:04:38.960Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}