> For the complete documentation index, see [llms.txt](https://docs.openiam.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.openiam.com/administration-guide/lifecycle/configure-provisioning.md).

# Configure provisioning

Configure the chain that turns a saved identity change into a target account, prove each outcome from the audit log, and recover a failed request.

## What this is, and when you need it

There is no "enable provisioning" form. Provisioning is what happens when a saved identity change meets a managed system the identity is entitled to, and the result depends on six configurations agreeing: the managed system, its policy map, its processors, the entitlement path, the two global flags, and its downstream ordering if you set one. This page is the chain: choosing the entitlement path, setting what a revocation does, testing the lifecycle in order, and proving each step from the audit log.

The attribute calculation is [Build a policy map](/administration-guide/lifecycle/policy-map.md); the managed-system fields are [Configure a managed system](/administration-guide/lifecycle/configure-managed-system.md).

The specific risk is fail-open. Three separate failures let a provisioning operation complete with part of its intended behaviour missing and no error anywhere: a business-rule service with no consumer, a processor that will not instantiate, and an Add or Update whose attribute set turns out to be empty. All three are in [The three fail-open paths](#the-three-fail-open-paths). Read [Change configuration safely](/administration-guide/start/change-safely.md) before your first live provisioning test.

## At a glance

|                          |                                                                                                                                                                                                                                                                                 |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **You will end up with** | One managed system whose `ON_DELETE` behaviour is set, and one entitlement path that puts a real account on the target — `PROVISIONING_ADD`, a `provisionconnectorrequest` document, a `connectorreply` with `SUCCESS`, and `LOGIN.PROV_STATUS` at `SAVED`                      |
| **Where**                | **Provisioning → Managed System**, `/webconsole/mngsystem?id=<MANAGED_SYSTEM_ID>`; the global flag is under **Administration → System Configuration**                                                                                                                           |
| **You need first**       | A managed system with a proven heartbeat and a policy map, one entitlement path chosen, `org.openiam.provision.service.flag` confirmed `true`, and whatever grants the entitlement you will use — confirm which role carries the system-configuration screen on your deployment |
| **Takes**                | 30–60 minutes to configure; the seven-part lifecycle test adds as long as your target takes to answer each operation                                                                                                                                                            |
| **Reversible**           | Partly — configuration and the grant are both reversible, but a revocation deletes the target account by default, and a completed target operation is never rolled back                                                                                                         |

## Before you begin

* A managed system with a proven heartbeat — [Verify connectivity to the target](/administration-guide/lifecycle/verify-connection.md).
* A policy map of type `USER_OBJECT` with, at minimum, a `PRINCIPAL` row and whatever attributes the target requires — [Build a policy map](/administration-guide/lifecycle/policy-map.md).
* One entitlement path chosen: a role, a group, a resource, a request, a business rule, or `ASSIGN_TO_ALL`. **One**, not two — removal through one path does not undo a grant through another.
* The `ON_DELETE` resource property set to the behaviour your policy wants. Absent means `DELETE`.
* `org.openiam.provision.service.flag` confirmed `true` under **Administration → System Configuration**. It ships `true`; with it off, every trigger below saves to the OpenIAM database only.
* `<TEST_USER>` and a disposable target container.

## Configure the chain

{% stepper %}
{% step %}

### Decide the entitlement path, once

Pick exactly one of: a business role that carries the managed system's resource, a technical role/group/resource assigned directly, an approved request, a synchronization-owned membership, or `ASSIGN_TO_ALL` for a genuinely universal target.

Encoding the same grant twice is the most common cause of "we revoked it and the account is still there": removal through one path leaves the other path still asserting the grant, and the next save re-provisions.
{% endstep %}

{% step %}

### Set `ON_DELETE` before you grant anything

`/webconsole/mngsystem?id=<MANAGED_SYSTEM_ID>`, **Attributes** table, name `ON_DELETE` in upper case, value `DELETE`, `DISABLE` or `UPDATE`. Only `DELETE` and `DISABLE` are interpreted consistently by both readers. Absent means `DELETE`.
{% endstep %}

{% step %}

### Attach processors only for an approved gap

Exhaust the managed-system fields, the policy-map source types, roles and business rules first. A processor widens the failure surface and must implement all nine abstract methods. [Attach a provisioning processor](/administration-guide/lifecycle/provisioning-processors.md).
{% endstep %}

{% step %}

### Capture the first operation

Add `Add` — and `Save` if your triggers use it — to **Simulation Requests**, then trigger the grant. Read the captured attribute set at `/webconsole/simulation?id=<MANAGED_SYSTEM_ID>` before applying. [Simulation mode](/administration-guide/lifecycle/simulation-mode.md). Leave those operations in **Simulation Requests** until the first create is proven; take them out only then.
{% endstep %}

{% step %}

### Test the lifecycle in order

{% hint style="warning" %}
Every part of this sequence writes to the target: the grant creates a real account, and part 6 revokes it, which deletes the account unless `ON_DELETE` says otherwise. Run the whole sequence against one `<TEST_USER>` in one disposable target container.
{% endhint %}

1. Create. Compare the outbound attribute set against your mapping specification, then read the account back **from the target**.
2. Change one mapped field. Confirm only that attribute changed on the target.
3. Change one *unmapped* OpenIAM field. Confirm no connector request was generated at all — an operation with nothing to send is meant to send nothing, and seeing that once is how you learn to recognise it.
4. Set, then reset, the password. Never log the value.
5. Disable, then enable. Check `LOGIN.STATUS` moved out of `PENDING_DISABLED` / `PENDING_ENABLED`.
6. Revoke the entitlement. Confirm the target behaviour matches `ON_DELETE`.
7. Repeat step 1 for the same user. Confirm no duplicate account.
   {% endstep %}
   {% endstepper %}

## Verification

The parent event for a user provisioning operation, and the child events beneath it, all carry one of the constants below. Search at `/webconsole/viewAuditLog`; open one at `/webconsole/auditLog?id=<auditLogId>`.

**Operation events** — set by the provisioning operation itself:

| Action                                                                                    | Operation                                                                                                                                                                                     |
| ----------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `PROVISIONING_ADD`                                                                        | Add                                                                                                                                                                                           |
| `PROVISIONING_MODIFY`                                                                     | Update                                                                                                                                                                                        |
| `PROVISIONING_SAVE`                                                                       | Save — **deprecated since 4.2.1.1** in favour of `PROVISIONING_ADD` and `PROVISIONING_MODIFY`. Still emitted by older callers, so do not remove it from an audit report or a retention policy |
| `PROVISIONING_DELETE`                                                                     | Delete                                                                                                                                                                                        |
| `PROVISIONING_ENABLE` / `PROVISIONING_DISABLE`                                            | Enable / Disable                                                                                                                                                                              |
| `PROVISIONING_SUSPEND` / `PROVISIONING_RESUME`                                            | Lock / Unlock                                                                                                                                                                                 |
| `PROVISIONING_SET_PASSWORD` / `PROVISIONING_RESET_PASSWORD`                               | SetPassword / ResetPassword                                                                                                                                                                   |
| `PROVISIONING_TEST`                                                                       | TestConnection                                                                                                                                                                                |
| `PROVISIONING_USER_SEARCH` / `PROVISIONING_GROUP_SEARCH` / `PROVISIONING_METADATA_SEARCH` | Search, group search, GetMetadata                                                                                                                                                             |
| `PROVISIONING_IN_ORDER`                                                                   | One downstream stream                                                                                                                                                                         |
| `SEND_SINGLE_PROVISION_EVENT`                                                             | SendSingleProvisionOperation                                                                                                                                                                  |
| `SIMULATE_PROVISIONING`                                                                   | The dispatcher captured the request instead of sending it                                                                                                                                     |
| `GROUP_PROVISIONING`                                                                      | A group provisioning operation                                                                                                                                                                |
| `DE_PROVISIONING`                                                                         | Deprovisioning                                                                                                                                                                                |
| `RETRY_PROVISIONING`                                                                      | A replayed request                                                                                                                                                                            |

**Per-identity children** — one per managed system, written where a parent operation fans out: `PROVISIONING_ENABLE_IDENTITY`, `PROVISIONING_DISABLE_IDENTITY`, `PROVISIONING_DELETE_IDENTITY`, `PROVISIONING_DEACTIVATE_IDENTITY`.

**Connector reply events** — written when the target answers, and the only events that describe the target rather than OpenIAM's intent:

| Action                                                     | Reply to                                           |
| ---------------------------------------------------------- | -------------------------------------------------- |
| `SAVE_CONNECTOR_RESPONSE`                                  | A user save                                        |
| `SAVE_GROUP_CONNECTOR_RESPONSE`                            | A group save                                       |
| `ENABLE_CONNECTOR_RESPONSE` / `DISABLE_CONNECTOR_RESPONSE` | Resume / Suspend                                   |
| `DELETE_CONNECTOR_RESPONSE`                                | Delete                                             |
| `RESET_PASSWORD_CONNECTOR_RESPONSE`                        | Reset password                                     |
| `SEARCH_CONNECTOR_RESPONSE`                                | Search                                             |
| `CONNECTOR_RESPONSE`                                       | The generic reply event                            |
| `REMOVE_ORPHAN`                                            | A `DirectDeleteConnectorRequest` against an orphan |

Every one of these has an `org.openiam.audit.log.prune.days.<ACTION>` property and every one ships **`-1`** — never prune. See [Audit actions and retention](/administration-guide/reference/audit-actions-and-retention.md).

**Other evidence, in order of how far it is from the browser:**

1. The document in `provisionrequest` — the encrypted request as submitted. A document with no `status` means the operation threw before a response was built.
2. The document in `provisionconnectorrequest` — the generated attribute set per managed system. This is where you confirm the policy map produced what you expected, and nothing extra.
3. The document in `provisionstream` — present only while a downstream chain is in flight. A stale one means a chain never completed.
4. The document in `connectorreply` — what the target said.
5. `LOGIN.PROV_STATUS`, `LOGIN.STATUS`, `LOGIN.LOCK_MARKER`.
6. The object in the target.

## When it goes wrong

| Symptom                                                                     | Cause                                                                                                                                                                                  | Fix                                                                                                                                                                                                          |
| --------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| :---                                                                        | :---                                                                                                                                                                                   | :---                                                                                                                                                                                                         |
| No provisioning request at all                                              | The identity is not entitled to the managed system; or `org.openiam.provision.service.flag` is `false`; or the managed system is inactive                                              | Check the entitlement path and the flag. An inactive managed system is skipped everywhere.                                                                                                                   |
| Audit says the operation succeeded, no `provisionconnectorrequest` document | There was nothing to send — every attribute value carried `NO_CHANGE`, or every row was silently skipped                                                                               | Read the policy map. A Groovy row that throws is swallowed at debug level and produces no attribute. [Build a policy map](/administration-guide/lifecycle/policy-map.md).                                    |
| Request exists, no reply ever arrives                                       | Runtime or messaging: no consumer on `<CONNECTOR_QUEUE>_Request`, or the connector never publishes to `_Response`                                                                      | [Verify connectivity to the target](/administration-guide/lifecycle/verify-connection.md). Preserve the stuck message before retrying.                                                                       |
| `LOGIN.PROV_STATUS = FAIL_SAVE`                                             | The connector or the target rejected the save, and the reply said so                                                                                                                   | Open the user's history and read the connector response's `lastError`. It is the target's own message.                                                                                                       |
| `LOGIN.PROV_STATUS = FAIL_PARENT`                                           | An upstream system in a downstream chain failed, so this one was never attempted                                                                                                       | Fix the upstream failure and re-trigger. Already-performed upstream operations are not rolled back.                                                                                                          |
| Terminal status is `PENDING_*` and never advances                           | The reply never arrived, or arrived and the identity row was gone (`Fatal Error. Identity for user doesn't exists…`)                                                                   | Check the reply index; check whether the identity was removed manually.                                                                                                                                      |
| Success everywhere, target has no record                                    | The connector acknowledged receipt without committing                                                                                                                                  | Read the account back from the target. For JDBC and script connectors, enable bounded connector debug logging and verify the executed statement, the key, the affected-row count and the transaction result. |
| Connector rejects one attribute                                             | Wrong target attribute name, wrong type, wrong multi-value handling, or a value over the target's length limit                                                                         | Fix the `ATTRIBUTE_MAP.ATTRIBUTE_NAME` — it goes on the wire exactly as written, so `sAMAccountName` and `samaccountname` are two different requests.                                                        |
| Account created with no entitlements                                        | Business-rule fail-open — the IDM log says `Business Rule Service is not run. Skip Business Rule processing` at warn level, and the audit entry carries no `BUSINESS_RULE_EXPLANATION` | Restore consumers on the business-rule evaluation queue, then run the recalculation deliberately — `PERFORM_BR_REPROVISION` ships **disabled**, so it will not catch up on its own.                          |
| Revoking the entitlement does not deprovision                               | Another entitlement path still grants it; or `ON_DELETE` resolves to something you did not intend; or the deprovisioning request failed                                                | Find every path to the resource before concluding. Read the `ON_DELETE` row.                                                                                                                                 |
| Import reports create failed, target account exists                         | Create succeeded and a later operation (password, enable, membership) failed                                                                                                           | Read the replies in operation order; repair rather than recreate.                                                                                                                                            |
| A newly created target account disappears                                   | Connector-internal cleanup after a failed create-stage step                                                                                                                            | Identify the first failing step. Do not disable cleanup before you understand the partial-object policy.                                                                                                     |
| Retry reports success and nothing happens                                   | The Webconsole's Retry button reports success without submitting anything                                                                                                              | Recover by correcting the cause and re-triggering. See the callout above.                                                                                                                                    |
| Duplicate account after a repair attempt                                    | An unlink-and-resave produced a new login while the old target object still existed                                                                                                    | Correlate the existing object instead. Reconciliation with `IDM_EXISTS__SYS_EXISTS` is the supported route.                                                                                                  |

## Rollback

Provisioning is "reversible with consequences" — [Reversibility, honestly](/administration-guide/start/change-safely.md#reversibility-honestly).

* **Configuration** is reversible: restore the recorded managed-system fields, policy-map rows, processor attribute rows and flag values. Untick **Active** on the managed system to stop further work immediately.
* **Target operations already dispatched are not.** You can re-grant a revoked entitlement, but the account may have been deleted, and the target's own history is not restored by OpenIAM.
* Disabling a managed system stops future requests. It does not undo completed ones, and it does not clear `PENDING_*` statuses on identities whose replies never arrived.

## Advanced behaviour and implementation notes

Everything below explains what the procedure above depends on. Read it when a step does not behave the way you expected, or before you design a runbook around provisioning.

## What triggers provisioning

Every one of these ends in a provisioning operation on a user or a group, and none of them is a screen called "Provisioning".

| Trigger                                                                 | Route into provisioning                                                                                                                                                               |
| ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| A user is saved in Webconsole or SelfService                            | Provisioned, **only if `org.openiam.provision.service.flag` is true**; otherwise the save is recorded in the OpenIAM database and goes no further                                     |
| An entitlement is granted or revoked                                    | Provisioned, if the same flag is on                                                                                                                                                   |
| An access request is approved                                           | Provisioned, if the same flag is on                                                                                                                                                   |
| A business rule adds or removes a role, group, resource or organization | The rule changes the user before it is saved, so the provisioning that follows carries the rule's result                                                                              |
| A synchronization with `IS_PROVISION = 'Y'` transforms a record         | Provisioned rather than saved straight to the database                                                                                                                                |
| A reconciliation situation response saves a user                        | Provisioned — this is why `ADD_TO_IDM` on a reconciliation can create accounts in systems you were not reconciling                                                                    |
| A group is saved                                                        | Provisioned, gated on the same flag                                                                                                                                                   |
| An SoD remediation removes entitlements                                 | Provisioned only when `org.openiam.provision.service.user.entitlements.flag` is on; otherwise the removal is recorded in OpenIAM and never reaches the target                         |
| A batch task fires                                                      | `PROV_BY_START_DATE_FUT`, `LEAVER_PROCESS`, `AUTO_REVOCATION`, `FUTURE_USER_PROV` — see [Advanced lifecycle patterns](/administration-guide/lifecycle/advanced-lifecycle-patterns.md) |
| `ASSIGN_TO_ALL` on a managed system, group or role                      | Its resource is added to every user on every Add and every Update, and provisioned with them                                                                                          |

Nothing on these screens says "this will provision". Confirm what a trigger actually sent from the user's identity list and the `PROVISIONING_*` audit entries for the save — see [Verification](#verification).

## The two global flags

Both are system properties in category **System**, edited at **Administration → System Configuration** (`/webconsole/propertyValues`). Both ship **`true`**.

| Key                                                    | UI label                                 | Shipped default | What `false` does                                                                                                                                                                                                                 |
| ------------------------------------------------------ | ---------------------------------------- | --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `org.openiam.provision.service.flag`                   | Is Provisioning Active?                  | `true`          | Every trigger above saves to the OpenIAM database only. No connector request is generated. **In addition**, a user save with no login is rejected with `LOGIN_REQUIRED`, because with provisioning off nothing will generate one. |
| `org.openiam.provision.service.user.entitlements.flag` | Is Entitlements via Provisioning Active? | `true`          | SoD remediation removes entitlements with a plain database save, so the removal is recorded in OpenIAM and never reaches the target. The user's entitlement list and the target then disagree, and nothing reports it.            |

{% hint style="danger" %}
`org.openiam.provision.service.flag = false` is not a safety switch you can leave on during a rollout. It changes what saving a user requires: every user you save must already have a login you entered yourself, so the screens that relied on OpenIAM generating the primary login start failing with `LOGIN_REQUIRED`. A synchronization that imports a user without a login hits the same wall and reports `NOT_FOUND` with the message `Logins collection must not be empty when provisioning is not enabled.` If you need to stop provisioning to one target, untick **Active** on that managed system instead.
{% endhint %}

Two more properties bound the same path: `openiam.default_managed_sys` ships **`0`** and names the OpenIAM repository itself — the managed system every user's primary login belongs to, and the one the password and enable/disable paths deliberately skip when running per-system processors. `org.openiam.mq.broker.encryption.key` ships `ff808181670838e0016708610547001b` and encrypts the stored request payload that retry depends on — see below.

## The `ON_DELETE` resource property

`ON_DELETE` is a resource-property row on the managed system's attributes table. It decides which operation the deprovisioning path runs. It is read by an exact-match lookup in two places, and in both, an absent or blank value is first coerced to the string `"DELETE"` — so the shipped behaviour of a managed system with no `ON_DELETE` row is *delete the account*.

| Where it is read                                                                         | Value                                         | Effect                           |
| ---------------------------------------------------------------------------------------- | --------------------------------------------- | -------------------------------- |
| On a **Delete** operation, choosing what to send the connector                           | `DELETE`, absent or blank                     | connector operation `Delete`     |
|                                                                                          | `DISABLE`                                     | connector operation `Disable`    |
|                                                                                          | `UPDATE`                                      | connector operation `Update`     |
|                                                                                          | any other non-blank value                     | `Delete`                         |
| On an **update** that deprovisions this resource, choosing the identity's pending status | `DELETE`, absent or blank                     | identity status `PENDING_DELETE` |
|                                                                                          | `DISABLE`                                     | `PENDING_DISABLE`                |
|                                                                                          | any other non-blank value, including `UPDATE` | `PENDING_UPDATE`                 |

{% hint style="warning" %}
The two readers disagree on unrecognised values: a typo such as `Delete` in lower case still sends the connector a `Delete`, but marks the identity `PENDING_UPDATE`. Only `DELETE` and `DISABLE` behave consistently in both. `UPDATE` changes the connector operation on a Delete and nowhere else. If the identity's status in the user's identity list disagrees with what the target actually did, this mismatch is why.
{% endhint %}

## The operation set

All 25 provisioning operations, which of them support pre- and post-processors, which register in the audit log, how each maps onto a connector call, and the "nothing to send" gate that silently sends no connector request at all, are in [The operation set](/administration-guide/lifecycle/provisioning-processors/provisioning-processor-reference.md#the-operation-set).

## The three fail-open paths

**Business rules.** Before evaluating business rules, OpenIAM checks that something is listening on the business-rule evaluation queue. If nothing is, it logs

{% code overflow="wrap" %}

```
Business Rule Service is not run. Skip Business Rule processing
```

{% endcode %}

at **warn** level in the IDM log and carries on. Provisioning then completes without any rule-driven grants, revocations, status changes or attribute stamping, with **no audit failure at all**. On a deployment where birthright access comes from business rules, this produces accounts with no entitlements and a clean audit record. Search the IDM log for that exact line whenever entitlements are missing across many users at once.

When rules do run, their evaluation is attached to the audit event as `BUSINESS_RULE_EXPLANATION`, filtered to the rules that matched or performed an action. That attribute is the only per-operation record of what the rules decided, and its absence on an otherwise successful operation is the observable symptom of this gap.

**Processors.** A pre- or post-processor that cannot be instantiated is replaced by a no-op, logging `Cannot instantiate <the value you configured>` at error level in the provisioning service log; the no-op's own methods log only at **debug**. A broken processor is therefore indistinguishable from no processor unless you set the logger category `org.openiam.idm.provisioning.preprocessor.user` to debug — see the [Installation Guide](/installation/installation.md) for how.

**The data-validation script.** If the script named by `org.openiam.idm.eventProcessor.groovy.script` cannot be instantiated, OpenIAM logs the failure at warn level and proceeds as if the script had returned `CONTINUE`. A validation script that fails to compile validates nothing and blocks nothing.

All three are control gaps, not successes. A green target account can be an incomplete one.

## Separate the account from its secondary operations

One business action commonly produces several target operations: create the object, set a password, enable it, add required group memberships, apply optional attributes. They succeed and fail independently, and the connector replies per operation.

The canonical example is an AD service account permitted to create a user in an OU but not to modify the membership of a protected or default group. The account exists, the membership does not, and a naive reading of the last reply says "create failed". Read the replies **in operation order** from the `connectorreply` index for this managed system and identity rather than summarising the request, and verify account status and password behaviour separately from every required membership. Grant only the rights the approved operations need, on the approved containers — a membership error is not a reason to assign a domain-wide administrative role. Recovery is [Recovering without retry, safely](#recovering-without-retry-safely).

### Connector cleanup after a partial create

Some AD connector versions remove a newly created account when a later create-stage step fails, so that a half-created disabled object is not left behind. The sequence is: create a disabled object, fail on password or enablement, delete the partial object. Inspecting only the final target state makes this look like an unexplained deletion.

Before you change deletion permissions or edit a connector script:

1. Establish the exact connector package version and read the create operation end to end, from the first target write through password, enable, membership and any cleanup.
2. Find the **first** failed step and fix its cause — password policy, attribute value, target permission, container or script.
3. Decide whether your target policy prefers automatic cleanup or a quarantined disabled object for repair.
4. If target deletion is prohibited, remove the delete right from the connector service account, or use the connector's own cleanup control — after testing the failure path. Then expect partial objects to remain, and assign an owner, an alert and a reconciliation rule for them.
5. Do not suppress the cleanup by editing the connector's own delete logic. That is a connector change, with its own version control, review, non-production test of both a requested delete and a failed create, and rollback — not a configuration change you can make and undo here.

The `ON_DELETE` resource property governs an **OpenIAM-requested** removal. It does not govern connector-internal cleanup during a failed create. Test both paths separately.

## Asynchronous completion, and what a post-processor cannot tell you

A connector request is fire and forget: OpenIAM publishes it to `<CONNECTOR_QUEUE>_Request` and does not wait. The reply arrives later on `<CONNECTOR_QUEUE>_Response`, and handling that reply is where `LOGIN.PROV_STATUS` is finally written — so the identity's provisioning status is the first place the target's answer becomes visible to you.

Consequences worth internalising:

* A browser `Save` proves OpenIAM accepted the initiating change. Nothing more.
* A **post-processor runs before the connector replies.** It cannot be used as a connector-success callback. The hook for "react to what the target said" is the connector response handler — [Reacting to a connector reply](/administration-guide/lifecycle/provisioning-processors/provisioning-processor-reference.md#reacting-to-a-connector-reply).
* The arrival of a reply is also what advances a downstream chain. See [the downstream section](/administration-guide/lifecycle/configure-managed-system.md#downstream-managed-system-honestly).

When the reply lands, OpenIAM writes the terminal state:

| Reply                                   | `LOGIN.PROV_STATUS` becomes                       | Also                                                                                                                                                                                                                                                             |
| --------------------------------------- | ------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Save / suspend / resume, `SUCCESS`      | `SAVED`                                           | `LOGIN.STATUS` moves `PENDING_DISABLED` → `DISABLED`, `PENDING_ENABLED` → `ENABLED`; `LOCK_MARKER` moves `PENDING_LOCK` → `LOCKED`, `PENDING_UNLOCK` → `NOT_LOCKED`. A non-empty `errorText` on a successful reply is added to the audit event as a **warning**. |
| Save / suspend / resume, failure        | `FAIL_SAVE`                                       | Statuses are left in their pending state                                                                                                                                                                                                                         |
| Delete, `SUCCESS` / failure             | `DELETED` / `FAIL_DELETE`                         |                                                                                                                                                                                                                                                                  |
| Upstream failure in a downstream stream | `FAIL_PARENT` on every not-yet-performed identity | Stream document deleted; performed operations **not** rolled back                                                                                                                                                                                                |

Note that a successful **suspend or resume** reply sets `PROV_STATUS = SAVED`, not `DISABLED` or `ENABLED`, even though those enum values exist. Judge enable/disable outcomes from `LOGIN.STATUS`, not from `PROV_STATUS`.

If the identity row is missing when the reply lands, the provisioning service log records — at error level, and as an audit warning on the operation — `Fatal Error. Identity for user doesn't exists, but this data has been sent to connector!. If you removed data from DB manually, please cleanup elasticsearch storage: <managedSysId>:<identity>`. That message means the connector was asked to act on an identity OpenIAM no longer has, which is almost always the result of a manual database edit.

## Recovering a failed request

The retry mechanism exists and works, and the Webconsole button for it does not. Both halves matter.

**What is stored.** Every create, update or delete provisioning request is written to the `provisionrequest` index with the submitted object serialised into `provisionObjectAsJSON` and **encrypted** with the key in `org.openiam.mq.broker.encryption.key`, alongside `provisionObjectType`, `operation` and `startDate`. That document is the retry token.

**How retry resolves it.** Retry starts from a **connector reply ID**, not a request ID, and walks:

`connectorreply` doc → `provisionRequestId` → `provisionconnectorrequest` doc → `provisionSessionRequestId` → `provisionrequest` doc

then decrypts `provisionObjectAsJSON` with the same key, rebuilds the object, and re-runs the recorded operation. Audited as `RETRY_PROVISIONING`.

Three ways it refuses:

| Failure                                                        | Response code       |
| -------------------------------------------------------------- | ------------------- |
| Blank reply ID, or any of the three documents missing          | `REQUEST_NOT_FOUND` |
| The `provisionrequest` document has no `startDate`             | `INVALID_REQUEST`   |
| Neither the encrypted nor the clear-text deserialisation works | `INTERNAL_ERROR`    |

The decryption failure is the one to plan for. On a mismatched key the IDM log says `Can't parse decrypted, it could be in old (clear) view. Try to deserialize without encryption` at warn level and the raw JSON is tried instead — which succeeds only for documents written before encryption was introduced. **Keep `org.openiam.mq.broker.encryption.key` identical on every node and preserved across upgrades**, or every stored request becomes unreplayable.

{% hint style="danger" %}
**The Retry button in the Webconsole's connector-reply dialog does nothing.** It reports success — `RETRY_POSTED_SUCCESS` — and no retry is submitted.

The retry mechanism itself is implemented and works when it is reached, but nothing in this build reaches it: the button is the only administrative route to it and the button is a stub. **Treat retry as unavailable** and recover by correcting the cause and re-triggering the original change. **You cannot confirm this from the screen** — the screen says it worked; the proof is the absence of a `RETRY_PROVISIONING` audit entry and of any new `provisionconnectorrequest` document afterwards. Confirm against your own release before designing an operational runbook around retry.
{% endhint %}

### Recovering without retry, safely

1. Read the `connectorreply` document. Record `status`, `lastError`, `operation`, `targetIdentity`, `date` and `provisionRequestId`.
2. Read the target by immutable identifier and by the proposed login. Decide whether the object exists.
3. Correct the cause: credential, endpoint, policy-map row, attribute value, target permission, connector script.
4. **If the target object exists**, correlate or repair it — run an update, or reconcile with `IDM_EXISTS__SYS_EXISTS` → `UPDATE_RES_FROM_IDM`. Do not create it again.
5. **If it does not exist**, re-trigger the original change (re-save the user, or re-apply the entitlement).
6. Verify no duplicate, and that `LOGIN.PROV_STATUS` reached a terminal success.

{% hint style="warning" %}
**Do not unlink the failed managed-system identity and re-save as your first move.** A failed create can leave an OpenIAM `LOGIN` row *and* a partially applied target object. Unlinking changes correlation state, and re-saving then generates a fresh login — which is how duplicate accounts are created. If a tested contract for that connector genuinely requires it: preserve the evidence, unlink only that one identity, confirm the granting role still applies, save once, and watch that specific request to completion. Stop immediately if a duplicate or an unexpected deprovisioning request appears. Never generalise it into a bulk repair.
{% endhint %}

## Related

* [Which log answers which question](/administration-guide/operations/which-log-to-read.md#raising-the-detail-level) — the logger categories that unlock a diagnostic line, and which log it lands in
* [Build a policy map](/administration-guide/lifecycle/policy-map.md) — what gets sent, and why a row is silently skipped.
* [Attach a provisioning processor](/administration-guide/lifecycle/provisioning-processors.md) — the hooks, and [their contract](/administration-guide/lifecycle/provisioning-processors/provisioning-processor-reference.md).
* [Configure a managed system](/administration-guide/lifecycle/configure-managed-system.md) — the settings this page assumes, and downstream ordering.
* [Simulation mode](/administration-guide/lifecycle/simulation-mode.md) — reviewing the generated request before it is sent.
* [Configure reconciliation](/administration-guide/lifecycle/configure-reconciliation.md) — detecting and repairing what provisioning got wrong.
* [System properties](/administration-guide/reference/system-properties.md) — the two flags and the encryption key in context.
* [Audit actions and retention](/administration-guide/reference/audit-actions-and-retention.md) — every action named above.

*Applies to OpenIAM 2026.8.1. Last reviewed 7 August 2026.*


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.openiam.com/administration-guide/lifecycle/configure-provisioning.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
