{"record":{"id":"45ae3cbed3b88915","repo":"passbolt/passbolt_api","slug":"please-use-json-extension-in-url-or-accept-application-json","errorCode":null,"errorMessage":"Please use .json extension in URL or accept application/json.","messagePattern":"Please use \\.json extension in URL or accept application/json\\.","errorType":"http","errorClass":"NotFoundException","httpStatus":404,"severity":"warning","filePath":"src/Controller/AppController.php","lineNumber":205,"sourceCode":"            'plugin' => null,\n            'controller' => 'AuthLogin',\n            'action' => 'loginGet',\n            '_method' => 'GET',\n        ]);\n\n        $this->loadComponent('Authentication.Authentication', [\n            'logoutRedirect' => $loginUrl,\n        ]);\n    }\n\n    /**\n     * @throws \\Cake\\Http\\Exception\\NotFoundException if request is not JSON\n     * @return void\n     */\n    protected function assertJson(): void\n    {\n        if (!$this->request->is('json')) {\n            throw new NotFoundException(__('Please use .json extension in URL or accept application/json.'));\n        }\n    }\n\n    /**\n     * @throws \\Cake\\Http\\Exception\\BadRequestException if request data is not an array or is empty\n     * @return void\n     */\n    protected function assertNotEmptyArrayData(): void\n    {\n        $data = $this->getRequest()->getData();\n        if (!is_array($data) || !count($data)) {\n            throw new BadRequestException(__('The request data can not be empty.'));\n        }\n    }\n\n    /**\n     * @inheritDoc\n     */","sourceCodeStart":187,"sourceCodeEnd":223,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/src/Controller/AppController.php#L187-L223","documentation":"assertJson is a guard used by all standard CRUD endpoints (create, delete, index, share, update, view) to enforce that the request is recognized as JSON. If the request neither has a .json extension nor is accepted as JSON (Accept: application/json or Content-Type application/json), CakePHP's request->is('json') is false and a NotFoundException is raised directing the client to request JSON.","triggerScenarios":"Calling any JSON API endpoint without a .json URL extension while the Accept header does not include application/json — e.g. curl without headers hitting /users/index, /shares/update, /resource/view, or a DELETE without .json.","commonSituations":"curl/Postman requests missing the Accept header; browser navigation to API routes; clients upgraded to endpoints that now assert JSON; proxies stripping Accept headers.","solutions":["Add .json to the endpoint URL (e.g. /users.json)","Send header Accept: application/json with the request","If using POST/PUT, also send Content-Type: application/json so CakePHP detects the JSON request"],"exampleFix":"// before\ncurl https://passbolt.example.org/resources/view/<id>\n// after\ncurl -H 'Accept: application/json' https://passbolt.example.org/resources/view/<id>.json","handlingStrategy":"validation","validationCode":"// before calling any CRUD endpoint\nif (!path.endsWith('.json')) path += '.json';\nheaders['Accept'] = 'application/json';","typeGuard":"const assertsJson = (headers: Record<string,string>) => /application\\/json/i.test(headers.Accept ?? '');","tryCatchPattern":"try { ... } catch (NotFoundException $e) { // 404 'Please use .json extension...'\n    retry with Accept: application/json and .json URL\n}","preventionTips":["Use a shared API client that appends .json and sets Accept automatically","Send Content-Type: application/json for bodies","Test endpoints via curl with explicit headers","Never browse API endpoints expecting HTML"],"tags":["http","json","content-negotiation","api"],"backgroundTag":"unexpected-response-shape","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"}