passbolt/passbolt_api · error · BadRequestException
This is not a valid Ajax/Json request.
Error message
This is not a valid Ajax/Json request.
What it means
The MFA organization settings POST endpoint only accepts JSON (Ajax) requests. When the incoming request does not declare an Accept/Content-Type of JSON, CakePHP's `$this->request->is('json')` check fails and the controller throws a BadRequestException. It exists to prevent HTML form posts from silently being treated as API calls.
Solutions
- Send the request with `Content-Type: application/json` and `Accept: application/json` headers
- Append `.json` to the URL so CakePHP routes it through the JSON extension
- In tests, use `$this->postJson()` or set the request headers before dispatch
Example fix
// before
curl -X POST -d '{"providers":["totp"]}' https://passbolt/mfa/policies/settings.json
// after
curl -X POST -H 'Content-Type: application/json' -H 'X-CSRF-Token: <token>' \
-d '{"providers":["totp"]}' https://passbolt/mfa/policies/settings.json Defensive patterns
Strategy: validation
Validate before calling
const isJson = (opts) => (opts.headers['Content-Type'] || '').includes('application/json') && (opts.headers['Accept'] || '').includes('application/json');
if (!isJson(requestOptions)) throw new Error('MFA org settings endpoint requires JSON headers'); Type guard
function isJsonRequest(headers) {
return typeof headers['Content-Type'] === 'string' && headers['Content-Type'].includes('application/json');
} Try / catch
null
Prevention
- Always send Content-Type: application/json and Accept: application/json to passbolt API endpoints
- Use the .json URL extension on API routes
- In integration tests, use the JSON-aware test helpers
When it happens
Trigger: POSTing to /mfa/policies/settings.json (or /mfa/policies/settings without .json) with Accept: text/html or missing Content-Type: application/json headers; submitting the MFA org-settings form via a plain HTML form post; a proxy or frontend client stripping the JSON Accept header.
Common situations: Calling the endpoint with curl without `-H 'Content-Type: application/json'`; older frontend code posting the legacy Duo settings format without the JSON content type; integration tests using `$this->post()` without `enableCsrfToken`/JSON headers.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Please use .json extension in URL or accept…
- Subscription key data is required.
- This is not a valid Ajax/Json request.
- This is not a valid Ajax/Json request.
- Ajax/Json request not supported.
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/2a4853861f070b77.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/PassboltCe/MultiFactorAuthentication/src/Controller/OrgSettings/MfaOrgSettingsPostController.php:41
use Passbolt\MultiFactorAuthentication\Utility\MfaOrgSettingsDuoBackwardCompatible;
class MfaOrgSettingsPostController extends MfaController
{
/**
* Handle Org Settings POST request
*
* @throws \App\Error\Exception\CustomValidationException if the user provided data do not validate
* @throws \Cake\Http\Exception\ForbiddenException if the user is not an admin
* @throws \Cake\Http\Exception\BadRequestException if the request is not made using Ajax/Json
* @param \Duo\DuoUniversal\Client|null $duoSdkClient Duo SDK Client
* @return void
*/
public function post(?Client $duoSdkClient = null): void
{
$this->User->assertIsAdmin();
if (!$this->request->is('json')) {
throw new BadRequestException(__('This is not a valid Ajax/Json request.'));
}
/** TODO: Remove this line and its class once the frontend has been updated to use the new format/names */
$data = MfaOrgSettingsDuoBackwardCompatible::remapSetDuoSettings((array)$this->getRequest()->getData());
$config = (new MfaOrgSettingsSetService())->setOrgSettings(
$data,
$this->User->getAccessControl(),
$duoSdkClient
);
$this->success(__('The multi factor authentication settings for the organization were updated.'), $config);
}
}
View on GitHub (pinned to 31c1bbc10f)