{"record":{"id":"963c41706b0956a3","repo":"passbolt/passbolt_api","slug":"exception-message-the-data-could-not-be-saved-metadata-key","errorCode":null,"errorMessage":"{exception message} The data could not be saved. Metadata key could not be shared with user id: {0}.","messagePattern":"(.+?) The data could not be saved\\. Metadata key could not be shared with user id: (.+?)\\.","errorType":"exception","errorClass":"MetadataKeyShareException","httpStatus":500,"severity":"error","filePath":"plugins/PassboltCe/Metadata/src/Service/MetadataKeyShareDefaultService.php","lineNumber":141,"sourceCode":"                }\n                $msg = __('The OpenPGP key data is not valid.');\n                throw new ValidationException($msg, $userMetadataPrivateKey, $metadataPrivateKeysTable);\n            }\n        } catch (Exception $exception) {\n            $msg = $exception->getMessage() . ' ';\n            $msg .= __('The data could not be validated.') . ' ';\n            $msg .= __('Metadata key could not be shared with user id: {0}.', $user->id);\n            throw new MetadataKeyShareException($msg, 500, $exception);\n        }\n\n        // Save private key entity for the user\n        try {\n            $metadataPrivateKeysTable->save($userMetadataPrivateKey, ['checkRules' => false]);\n        } catch (Exception $exception) {\n            $msg = $exception->getMessage() . ' ';\n            $msg .= __('The data could not be saved.') . ' ';\n            $msg .= __('Metadata key could not be shared with user id: {0}.', $user->id);\n            throw new MetadataKeyShareException($msg, 500, $exception);\n        }\n    }\n\n    /**\n     * @inheritDoc\n     */\n    public function onFailure(Exception $exception): void\n    {\n        Log::error($exception->getMessage());\n        if (Configure::read('debug')) {\n            Log::error($exception->getTraceAsString());\n        }\n    }\n\n    /**\n     * @param string $clearText private key object in json format\n     * @return void\n     */","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltCe/Metadata/src/Service/MetadataKeyShareDefaultService.php#L123-L159","documentation":"Wrapper error thrown when the database save of the validated MetadataPrivateKey entity for the target user throws. The original message is concatenated with 'The data could not be saved. Metadata key could not be shared with user id: {0}.' and rethrown as MetadataKeyShareException (HTTP 500). Note the save runs with checkRules => false, so this is almost always a persistence-layer failure, not validation.","triggerScenarios":"Calling shareMetadataKeyWithUsers/shareMetadataKeysWithUser when the INSERT into metadata_private_keys fails: database connection loss, unique/duplicate key constraint (row created concurrently), lock timeout, or a SQL error.","commonSituations":"Two admins sharing the same metadata key with the same user concurrently; MySQL/Postgres connection dropped mid-operation; migration missing so the table/column does not exist (after upgrade without running migrations).","solutions":["Check the database is reachable and migrations are up to date (run pending migrations)","Look for a duplicate metadata_private_keys row created concurrently for the same (metadata_key_id, user_id); deduplicate and retry","Retry the share operation — it is safe to re-run once the conflicting row is handled","Inspect DB logs for the underlying SQL error surfaced in the prefixed exception message"],"exampleFix":"// before: concurrent shares race on the same user\nforeach ($userIds as $uid) { $service->shareMetadataKeyWithUser($users[$uid], $serverKey); }\n// after: serialize the share per (key,user) to avoid duplicate-key races\n$lock = acquireLock('metadata_share_' . $serverKey->metadata_key_id . '_' . $user->id);\nif ($lock) { $service->shareMetadataKeyWithUser($user, $serverKey); releaseLock($lock); }","handlingStrategy":"retry","validationCode":"$this->metadataPrivateKeysTable->getSchema()->columns(); // ensure table exists post-migration\n$dup = $metadataPrivateKeysTable->exists(['metadata_key_id' => $keyId, 'user_id' => $userId]);\nif ($dup) { /* remove or skip before save */ }","typeGuard":null,"tryCatchPattern":"try {\n    $service->shareMetadataKeyWithUser($user, $serverKey);\n} catch (MetadataKeyShareException $e) {\n    if (str_contains($e->getMessage(), 'could not be saved')) {\n        // duplicate-key/connection failure: dedupe then retry once\n        $this->dedupePrivateKeysRow($keyId, $user->id);\n        retryShare($user, $serverKey);\n    }\n}","preventionTips":["Keep migrations current after every upgrade so metadata_private_keys schema matches code","Serialize concurrent share operations per (metadata_key_id, user_id) with a lock","Monitor database connectivity/lock timeouts during batch shares","Design shares as idempotent so retries are safe"],"tags":["database","metadata-key","persistence","cakephp"],"backgroundTag":"database-write-failed","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"}