{"record":{"id":"ffa16f86bb404950","repo":"passbolt/passbolt_api","slug":"invalid-schema-for-scim-patch-request","errorCode":null,"errorMessage":"Invalid schema for SCIM PATCH REQUEST","messagePattern":"Invalid schema for SCIM PATCH REQUEST","errorType":"exception","errorClass":"Cake\\Http\\Exception\\BadRequestException","httpStatus":400,"severity":"error","filePath":"plugins/PassboltEe/Scim/src/Utility/Object/PatchRequest.php","lineNumber":62,"sourceCode":"\n        $this->operations = [];\n        $operations = $data['Operations'] ?? [];\n        foreach ((array)$operations as $operationData) {\n            $this->operations[] = (new Operation())->setFromScim($operationData);\n        }\n\n        return $this;\n    }\n\n    /**\n     * @param array $data\n     * @return void\n     */\n    protected function validateScimData(array $data): void\n    {\n        $schemas = $data['schemas'] ?? [];\n        if (!in_array(SchemaIdentifier::API_PATCH_OPERATION, $schemas)) {\n            throw new BadRequestException('Invalid schema for SCIM PATCH REQUEST');\n        }\n        if (!array_key_exists('Operations', $data)) {\n            throw new BadRequestException('Invalid data to create a SCIM PATCH REQUEST');\n        }\n    }\n\n    /**\n     * @inheritDoc\n     */\n    public function toSCIM(): array\n    {\n        $data = [\n            'schemas' => [SchemaIdentifier::API_PATCH_OPERATION],\n            'Operations' => [],\n        ];\n        foreach ($this->operations as $operation) {\n            $data['Operations'][] = $operation->toSCIM();\n        }","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltEe/Scim/src/Utility/Object/PatchRequest.php#L44-L80","documentation":"A SCIM PATCH request must declare its schema via a 'schemas' array containing the patch-operation schema identifier (SchemaIdentifier::API_PATCH_OPERATION, urn:ietf:params:scim:api:messages:2.0:PatchOp). validateScimData throws this BadRequestException when the identifier is missing from the payload's schemas, indicating the request is not a conformant SCIM PATCH message.","triggerScenarios":"PATCH /scim/v2/Users/{id} or /Groups/{id} with a body whose 'schemas' array omits the PatchOp URN, or has no 'schemas' key at all.","commonSituations":"Client sends a bare {'Operations': [...]} body without the schemas envelope; wrong URN copied from SCIM 1.1 docs; proxy/middleware strips or rewrites the body; custom integration omits metadata.","solutions":["Add \"schemas\": [\"urn:ietf:params:scim:api:messages:2.0:PatchOp\"] to the PATCH request body.","Verify the exact URN expected by SchemaIdentifier::API_PATCH_OPERATION in the plugin source.","Check SchemaIdentifier for the identifier and align your client.","Test the PATCH payload with a SCIM validator or curl against a known-good example."],"exampleFix":"// before\n{\"Operations\": [{\"op\": \"replace\", \"path\": \"active\", \"value\": true}]}\n// after\n{\"schemas\": [\"urn:ietf:params:scim:api:messages:2.0:PatchOp\"], \"Operations\": [{\"op\": \"replace\", \"path\": \"active\", \"value\": true}]}","handlingStrategy":"validation","validationCode":"const PATCH_SCHEMA = 'urn:ietf:params:scim:api:messages:2.0:PatchOp';\nif (!in_array(PATCH_SCHEMA, $body['schemas'] ?? [], true)) {\n    throw new InvalidArgumentException('PATCH body must declare the PatchOp schema URN');\n}","typeGuard":"function hasPatchSchema(mixed $body): bool {\n    return is_array($body)\n        && in_array('urn:ietf:params:scim:api:messages:2.0:PatchOp', $body['schemas'] ?? [], true);\n}","tryCatchPattern":"try {\n    $patchRequest = PatchRequest::setFromScim($data);\n} catch (BadRequestException $e) {\n    // fix schemas envelope before retry\n}","preventionTips":["Always include the PatchOp URN in PATCH bodies.","Use a shared payload builder that injects the schemas envelope.","Diff payloads against RFC 7644 PATCH examples.","Add contract tests for SCIM PATCH requests."],"tags":["scim","patch","schema"],"backgroundTag":"schema-validation-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"}