{"record":{"id":"f1c704e76dbf6722","repo":"passbolt/passbolt_api","slug":"the-metadata-could-not-be-encrypted-with-the-metadata-key-id","errorCode":null,"errorMessage":"The metadata could not be encrypted with the metadata key id: {0}.","messagePattern":"The metadata could not be encrypted with the metadata key id: (.+?)\\.","errorType":"http","errorClass":"InternalErrorException","httpStatus":500,"severity":"error","filePath":"plugins/PassboltCe/Metadata/src/Service/Migration/MigrateAllV4ResourcesToV5Service.php","lineNumber":216,"sourceCode":"     * @throws \\Cake\\Datasource\\Exception\\RecordNotFoundException When there is no metadata key record.\n     * @throws \\Cake\\Http\\Exception\\InternalErrorException When resource type mapping is does not exist.\n     */\n    private function migrateShared(MetadataResourceDto $dto, Resource $resource): void\n    {\n        $metadataArray = $dto->getClearTextMetadata();\n        $metadataKey = $this->getMetadataKeyForEncryption();\n\n        try {\n            $gpg = OpenPGPBackendFactory::get();\n            $gpg->clearKeys();\n            $gpg = $this->setSignKeyWithServerKey($gpg);\n            $gpg = $this->setEncryptKeyWithMetadataKey($gpg, $metadataKey);\n            $metadataClearText = json_encode($metadataArray, JSON_THROW_ON_ERROR);\n            $metadataEncrypted = $gpg->encrypt($metadataClearText, true);\n        } catch (Exception $exception) {\n            $msg = $exception->getMessage() . ' ';\n            $msg .= __('The metadata could not be encrypted with the metadata key id: {0}.', $metadataKey->id);\n            throw new InternalErrorException($msg, 500, $exception);\n        }\n\n        $this->updateResource($resource, [\n            'name' => null,\n            'username' => null,\n            'uri' => null,\n            'description' => null,\n            'resource_type_id' => $this->getV5ResourceType($resource->resource_type_id),\n            'metadata' => $metadataEncrypted,\n            'metadata_key_id' => $metadataKey->id,\n            'metadata_key_type' => 'shared_key',\n            //TODO support nullable resource.modified_by to allow server side modification\n            //'modified_by' => null,\n        ]);\n    }\n\n    /**\n     * @param string $v4ResourceTypeId V4 Resource type identifier to get mapping from.","sourceCodeStart":198,"sourceCodeEnd":234,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltCe/Metadata/src/Service/Migration/MigrateAllV4ResourcesToV5Service.php#L198-L234","documentation":"The shared-resource migration path encrypts metadata with the server metadata key. If setEncryptKeyWithMetadataKey or encrypt() fails (key missing from keyring, invalid key data), the underlying exception is rethrown as InternalErrorException with this message identifying the failing metadata key id.","triggerScenarios":"migrate() -> migrateShared() loads the active metadata key, calls setEncryptKeyWithMetadataKey() then encrypt(); occurs when the metadata private key is absent from the server keyring, the key data fails assertMetadataKey validation, or the key is expired/revoked.","commonSituations":"Server restored without the metadata private key in its keyring; metadata key rotated and old fingerprint no longer resolvable; GnuPG keyring permission problems under the web-server user; corrupted metadata_keys row.","solutions":["Verify the metadata key exists in the keyring (gpg --list-keys <fingerprint>); re-import the metadata private key if missing","Enable debug and rerun the migration — the wrapped exception message is prepended and shows the root cause","Run MetadataKeysHealthCheck / re-import the metadata key via the server key import command","Validate the metadata_keys row (fingerprint, armored_key) is intact; restore from backup if corrupted"],"exampleFix":"// before\n$gpg = $this->setEncryptKeyWithMetadataKey($gpg, $metadataKey); // throws if key not importable\n// after: ensure key is in keyring first\n$this->getMetadataKeysService()->importMetadataKeyInKeyring($metadataKey);\n$gpg = $this->setEncryptKeyWithMetadataKey($gpg, $metadataKey);","handlingStrategy":"try-catch","validationCode":"$key = $this->MetadataKeys->find()\n    ->where(['id' => $metadataKey->id, 'deleted' => false])\n    ->firstOrFail();\nif (!is_string($key->fingerprint) || strlen($key->fingerprint) !== 40) {\n    throw new \\LogicException('Metadata key fingerprint missing');\n}\n// ensure import\n$this->getMetadataKeysService()->importMetadataKeyInKeyring($key);","typeGuard":"function isUsableMetadataKey(\\Passbolt\\Metadata\\Model\\Entity\\MetadataKey $k): bool {\n    return $k->deleted === false && $k->expired === null\n        && is_string($k->fingerprint) && strlen($k->fingerprint) === 40\n        && is_string($k->armoredKey);\n}","tryCatchPattern":"try {\n    $gpg = $this->setEncryptKeyWithMetadataKey($gpg, $metadataKey);\n    $metadataEncrypted = $gpg->encrypt($metadataClearText, true);\n} catch (\\Exception $e) {\n    // re-import key into keyring, then retry once\n}","preventionTips":["Back up and restore the GnuPG keyring together with the database during server migrations","Run metadata key health checks before bulk v5 migrations","Never delete/expire the active metadata key while migrations are pending"],"tags":["openpgp","encryption","migration","metadata-key","keyring"],"backgroundTag":"http-error-response","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"}