{"record":{"id":"d1075aaa823e2272","repo":"passbolt/passbolt_api","slug":"the-metadata-private-key-cleartext-data-is-not-valid","errorCode":null,"errorMessage":"The metadata private key cleartext data is not valid.","messagePattern":"The metadata private key cleartext data is not valid\\.","errorType":"http","errorClass":"InternalErrorException","httpStatus":500,"severity":"error","filePath":"plugins/PassboltCe/Metadata/src/Service/MetadataKeyShareDefaultService.php","lineNumber":187,"sourceCode":"        } catch (Exception $exception) {\n            if (Configure::read('debug')) {\n                Log::error($clearText);\n            }\n            $msg = __('The metadata private key cleartext data should be in JSON format.');\n            throw new InternalErrorException($msg, 500, $exception);\n        }\n        if (!is_array($decoded) || empty($decoded)) {\n            $msg = __('The metadata private key cleartext data should not be empty.');\n            throw new InternalErrorException($msg);\n        }\n\n        $form = new MetadataCleartextPrivateKeyForm();\n        if (!$form->validate($decoded)) {\n            if (Configure::read('debug')) {\n                Log::error(json_encode($form->getErrors()));\n            }\n            $msg = __('The metadata private key cleartext data is not valid.');\n            throw new InternalErrorException($msg);\n        }\n    }\n\n    /**\n     * Get the OpenPGP Backend ready to decrypt with server key\n     *\n     * @param \\App\\Utility\\OpenPGP\\OpenPGPBackend $gpg for example OpenPGPBackendFactory::get()\n     * @param string|null $createdBy uuid of user\n     * @return \\App\\Utility\\OpenPGP\\OpenPGPBackend backend configured to use server keys\n     * @throws \\Cake\\Http\\Exception\\InternalErrorException if the server key cannot be loaded\n     */\n    private function setKeyForVerify(OpenPGPBackend $gpg, ?string $createdBy = null): OpenPGPBackend\n    {\n        // Use server key if no user is defined in createdBy\n        if ($createdBy === null) {\n            return $this->setVerifyKeyWithServerKey($gpg);\n        }\n","sourceCodeStart":169,"sourceCodeEnd":205,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltCe/Metadata/src/Service/MetadataKeyShareDefaultService.php#L169-L205","documentation":"assertPrivateKey throws InternalErrorException when the decoded cleartext array fails validation by MetadataCleartextPrivateKeyForm. The data is valid non-empty JSON but missing required fields (e.g. objectType, armored_key) or violating the form's schema for a metadata private key cleartext.","triggerScenarios":"shareMetadataKeyWithUser decrypts the server copy and validates the cleartext structure; a payload missing keys like 'objectType' => 'PASSBOLT_METADATA_PRIVATE_KEY' or a valid 'armored_key', or with extra/invalid fields, fails $form->validate($decoded) and raises this error (form errors logged in debug).","commonSituations":"Keys imported by tooling that produced a slightly different JSON shape; passbolt version mismatch where the cleartext schema changed; hand-crafted migration/import scripts that omitted required properties.","solutions":["Enable debug to see json_encode($form->getErrors()) and identify which fields fail","Compare the cleartext against the MetadataCleartextPrivateKeyForm schema and fix missing/invalid fields (objectType, armored_key, etc.)","Re-import or regenerate the metadata private key using the official passbolt migration tooling/commands rather than custom scripts","Ensure all plugins are upgraded together so the cleartext schema version matches what the server expects"],"exampleFix":"// before: incomplete cleartext\n{\"armored_key\": \"-----BEGIN PGP PRIVATE KEY BLOCK-----...\"}\n// after: schema-conformant cleartext\n{\"objectType\": \"PASSBOLT_METADATA_PRIVATE_KEY\", \"armored_key\": \"-----BEGIN PGP PRIVATE KEY BLOCK-----...\", \"created\": \"2024-01-01T00:00:00+00:00\", \"modified\": \"2024-01-01T00:00:00+00:00\"}","handlingStrategy":"validation","validationCode":"$decoded = json_decode($cleartext, true, 2);\n$form = new \\Passbolt\\Metadata\\Form\\MetadataCleartextPrivateKeyForm();\nif (!is_array($decoded) || !$form->validate($decoded)) {\n    throw new \\DomainException('Cleartext schema invalid: ' . json_encode($form->getErrors()));\n}","typeGuard":"function passesCleartextForm(array $decoded): bool {\n    return isset($decoded['objectType'], $decoded['armored_key'])\n        && $decoded['objectType'] === 'PASSBOLT_METADATA_PRIVATE_KEY'\n        && is_string($decoded['armored_key']);\n}","tryCatchPattern":"try {\n    $service->shareMetadataKeysWithUser($uac, $userIds, $keyId);\n} catch (MetadataKeyShareException $e) {\n    if (str_contains($e->getMessage(), 'cleartext data is not valid')) {\n        // inspect MetadataCleartextPrivateKeyForm errors in debug logs and re-import conformant data\n    }\n}","preventionTips":["Generate cleartext envelopes only via passbolt's official forms/DTOs, never hand-rolled arrays","Use the official migration commands (e.g. metadata key migration shell) instead of ad-hoc scripts","Pin client and server to compatible plugin versions when importing keys","Run assertPrivateKey-equivalent validation as a pre-import check"],"tags":["openpgp","metadata-key","form-validation","schema"],"backgroundTag":"schema-validation-failed","analyzedSha":"31c1bbc10f32808a607fa9bd81891e898779c0bc","analyzedAt":"2026-09-17T00:04:38.960Z","contentChangedAt":"2026-09-17T00:04:38.960Z","schemaVersion":2},"datasetVersion":"2026-09-21T09:17:21.228Z"}