{"record":{"id":"13cf2aafa68b2c13","repo":"passbolt/passbolt_api","slug":"subscription-key-data-is-required-13cf2a","errorCode":null,"errorMessage":"Subscription key data is required.","messagePattern":"Subscription key data is required\\.","errorType":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"plugins/PassboltEe/Subscription/src/Controller/Subscriptions/SubscriptionsUpdateController.php","lineNumber":43,"sourceCode":"use Passbolt\\Subscription\\Service\\Subscriptions\\SubscriptionKeySaveService;\n\n/**\n * Class SubscriptionsUpdateController\n */\nclass SubscriptionsUpdateController extends AppController\n{\n    /**\n     * @return void\n     */\n    public function update(): void\n    {\n        if (!$this->User->isAdmin()) {\n            throw new ForbiddenException(__('You are not allowed to access this location.'));\n        }\n\n        $keyString = $this->getRequest()->getData('data');\n        if (!is_string($keyString) || trim($keyString) === '') {\n            throw new BadRequestException(__('Subscription key data is required.'));\n        }\n\n        try {\n            $keyDto = (new SubscriptionKeySaveService())->save($keyString, $this->User->getAccessControl());\n        } catch (SubscriptionSignatureException $e) {\n            throw new BadRequestException($e->getMessage());\n        } catch (SubscriptionException $e) {\n            throw new PaymentRequiredException($e->getMessage(), $e->getErrors());\n        }\n\n        // POST and PUT both land here for backwards compatibility.\n        // Preserve the historical success messages of the now-deleted\n        // SubscriptionsCreateController (POST) and this controller (PUT) so the\n        // legacy SubscriptionsCreateControllerTest keeps passing unchanged.\n        $message = $this->getRequest()->is('post')\n            ? __('The subscription was created.')\n            : __('The subscription was updated.');\n","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltEe/Subscription/src/Controller/Subscriptions/SubscriptionsUpdateController.php#L25-L61","documentation":"The controller requires a non-empty string in the 'data' form field containing the subscription key. When the field is missing, not a string, or whitespace-only, a 400 is thrown before any save attempt.","triggerScenarios":"POST /subscription.jsonapi without the data field, with data=, or with data=\"   \"; sending JSON body instead of form data so getData('data') returns null.","commonSituations":"Scripts forgetting the -d \"data=...\" form field; copying an empty key from email; curl sending multipart without the field name matching exactly 'data'.","solutions":["Send the subscription key as form field data=<key string>","Ensure the key string is copied completely including BEGIN/END markers","If sending JSON, use the expected form-encoded body the controller reads via getData('data')","Verify the Content-Type is application/x-www-form-urlencoded (or multipart) so CakePHP parses the field"],"exampleFix":"// before\ncurl -X POST .../subscription.jsonapi -H \"Authorization: ...\"  # no body\n// after\ncurl -X POST .../subscription.jsonapi -H \"Authorization: ...\" -d \"data=-----BEGIN PGP MESSAGE----- ... -----END PGP MESSAGE-----\"","handlingStrategy":"validation","validationCode":"const key = subscriptionKey.trim();\nif (!key) throw new Error('Subscription key data is required');\nconst body = new URLSearchParams({data: subscriptionKey});\n// then send body as application/x-www-form-urlencoded","typeGuard":"function hasSubscriptionKey(v) { return typeof v === 'string' && v.trim() !== ''; }","tryCatchPattern":"if (res.status === 400 && body.message.includes('Subscription key data is required')) {\n  console.error('Send the key in the form field \"data\"');\n}","preventionTips":["Always send the key under the exact form field name 'data'","Use application/x-www-form-urlencoded (or multipart), not JSON","Validate the key is non-empty before sending"],"tags":["bad-request","missing-field","subscription","form-data"],"backgroundTag":"empty-required-field","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"}