{"record":{"id":"3d37df147c78ee1b","repo":"passbolt/passbolt_api","slug":"the-jwt-public-key-could-not-be-written","errorCode":null,"errorMessage":"The JWT public key could not be written.","messagePattern":"The JWT public key could not be written\\.","errorType":"http","errorClass":"InvalidJwtKeyPairException","httpStatus":500,"severity":"error","filePath":"plugins/PassboltCe/JwtAuthentication/src/Service/AccessToken/JwtKeyPairService.php","lineNumber":86,"sourceCode":"        $secretKeyPath = $this->getSecretKeyPath();\n        $publicKeyPath = $this->getPublicKeyPath();\n\n        try {\n            $pk = openssl_pkey_new($config);\n            if ($pk === false) {\n                throw new Exception('The JWT private key could not be created.');\n            }\n            $export = openssl_pkey_export_to_file($pk, $secretKeyPath);\n            if ($export === false) {\n                throw new Exception('The JWT private key could not be written.');\n            }\n            $publicKey = openssl_pkey_get_details($pk)['key'] ?? false;\n            if ($publicKey === false) {\n                throw new Exception('The JWT public key could not be extracted.');\n            }\n            $export = file_put_contents($publicKeyPath, $publicKey);\n            if ($export === false) {\n                throw new Exception('The JWT public key could not be written.');\n            }\n\n            $permission = 0640;\n            $res = chmod($secretKeyPath, $permission);\n            if (!$res) {\n                throw new Exception(\"The permission of $secretKeyPath could not be set to $permission.\");\n            }\n            $res = chmod($publicKeyPath, $permission);\n            if (!$res) {\n                throw new Exception(\"The permission of $publicKeyPath could not be set to $permission.\");\n            }\n        } catch (Throwable $e) {\n            throw new InvalidJwtKeyPairException($e->getMessage());\n        }\n    }\n\n    /**\n     * Validate the key pair validity as defined by the public and secret services.","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltCe/JwtAuthentication/src/Service/AccessToken/JwtKeyPairService.php#L68-L104","documentation":"createKeyPair() writes the extracted public key PEM to the public key path with file_put_contents(). A false return triggers this error, wrapped in InvalidJwtKeyPairException. It means the public key file could not be created or overwritten at getPublicKeyPath().","triggerScenarios":"file_put_contents($publicKeyPath, $publicKey) returns false because config/jwt/ is missing, not writable by the current process, the path exists as a directory, or the filesystem is full/read-only.","commonSituations":"Web-server user (www-data) differs from CLI user that created config/jwt; SELinux contexts; deploying to immutable containers where config/ is read-only at runtime.","solutions":["Ensure config/jwt exists and is writable by the runtime user: chown -R www-data:www-data config/jwt","Check the public key path is a regular writable file, not a directory (ls -la config/jwt)","Verify disk space and mount writability (df -h; touch config/jwt/test)","If the container FS is read-only, generate the keys at build time or mount config/jwt as a writable volume"],"exampleFix":"// before\n$export = file_put_contents($publicKeyPath, $publicKey);\n// after\nif (!is_writable(dirname($publicKeyPath))) {\n    chmod(dirname($publicKeyPath), 0770); // or chown to runtime user\n}\n$export = file_put_contents($publicKeyPath, $publicKey);","handlingStrategy":"validation","validationCode":"if (!is_dir($dir)) { mkdir($dir, 0770, true); }\nif (!is_writable($dir)) { throw new \\RuntimeException(\"{$dir} not writable by \" . get_current_user()); }","typeGuard":null,"tryCatchPattern":"try { $service->createKeyPair(); } catch (InvalidJwtKeyPairException $e) { // chown/chmod config/jwt to the runtime user, then retry }","preventionTips":["Provision config/jwt as a writable volume before first run","Match CLI and web-server users for key management","Add writability checks to deployment health checks"],"tags":["jwt","file-write","permissions"],"backgroundTag":"file-write-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"}