{"record":{"id":"3e87d3b5ecc5223d","repo":"passbolt/passbolt_api","slug":"the-metadata-key-id-should-be-a-valid-uuid","errorCode":null,"errorMessage":"The metadata key ID should be a valid UUID.","messagePattern":"The metadata key ID should be a valid UUID\\.","errorType":"validation","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"plugins/PassboltCe/Metadata/src/Controller/MetadataKeyDeleteController.php","lineNumber":40,"sourceCode":"use Passbolt\\Metadata\\Service\\MetadataKey\\MetadataKeyDeleteService;\n\nclass MetadataKeyDeleteController extends AppController\n{\n    /**\n     * Delete a given metadata key\n     *\n     * @param string $id key uuid\n     * @return void\n     * @throws \\Cake\\Http\\Exception\\NotFoundException if the key does not exist or is already deleted\n     * @throws \\Cake\\Http\\Exception\\BadRequestException if the key id format is Invalid or some items are still using the key\n     * @throws \\Cake\\Http\\Exception\\InternalErrorException if there was an issue during the save/delete\n     */\n    public function delete(string $id): void\n    {\n        $this->assertJson();\n        $this->User->assertIsAdmin();\n        if (!Validation::uuid($id)) {\n            throw new BadRequestException(__('The metadata key ID should be a valid UUID.'));\n        }\n\n        (new MetadataKeyDeleteService())->delete($this->User->getAccessControl(), $id);\n        $this->success(__('The operation was successful.'));\n    }\n}\n","sourceCodeStart":22,"sourceCodeEnd":47,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltCe/Metadata/src/Controller/MetadataKeyDeleteController.php#L22-L47","documentation":"Format guard in the metadata key delete action: the id route parameter fails Validation::uuid(), so the metadata key identifier is malformed and the delete is rejected with 400 before the key is looked up.","triggerScenarios":"DELETE request to /metadata/keys/{id} where {id} is not a valid UUID (e.g. a fingerprint, slug, numeric id, or truncated string).","commonSituations":"Clients storing key fingerprints instead of the metadata key UUID; hand-built URLs; typos when copying an id; older v4 resource-key identifiers used against the v5 endpoint.","solutions":["Send the metadata key's UUID as the path parameter.","Look up the correct key id first via GET /metadata/keys and use the 'id' field.","Fix URL construction in the client; validate the id is a UUID before calling."],"exampleFix":"// before\nfetch(`/metadata/keys/${key.fingerprint}`, {method:'DELETE'});\n// after\nfetch(`/metadata/keys/${key.id}`, {method:'DELETE'});","handlingStrategy":"validation","validationCode":"const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\nif (!UUID_RE.test(id)) throw new Error('metadata key id must be a UUID');","typeGuard":"const isUuid = (v) => typeof v === 'string' && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(v);","tryCatchPattern":"try { await api.del(`/metadata/keys/${id}`); } catch (e) { if (e.response?.status === 400) { id = await resolveKeyIdFromApi(); retry(); } else throw e; }","preventionTips":["Store and pass the 'id' field from API responses, never fingerprints.","Validate UUIDs client-side before building URLs.","Never hand-edit id segments in URLs."],"tags":["uuid","validation","api","bad-request"],"backgroundTag":"invalid-identifier-format","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"}