---
cuppy_hub: azure
cuppy_path: reference/policy/effects-and-errors.md
cuppy_section: docs
cuppy_doc: 59K7-48G9
cuppy_doc_uuid: 4611bc8b-b12f-4077-8a85-50322199b6b0
cuppy_permalink: https://cuppy.io/azure/d/59K7-48G9
cuppy_version: 1
cuppy_updated: 2026-10-23T16:16:52.575Z
cuppy_canonical: https://cuppy.io/azure/docs/reference/policy/effects-and-errors
cuppy_mcp: https://cuppy.io/mcp
cuppy_body_sha256: 6aa7c1e81421bd77b15ea6ea9c249011ed0145bfc11b56c64d4e19238957f2a4
# cuppy_body_sha256 is over the document body ALONE, excluding both generated blocks.
---


# Azure Policy — effects, timing and RequestDisallowedByPolicy

**Azure Policy is not a permission.** It runs after RBAC has allowed the call, so Owner can still be refused. A refusal names the assignment and the definition that blocked it, and the fix is almost always to change the request so it complies (a SKU, a region, a tag, `publicNetworkAccess: Disabled`), not to fight the policy.

## Reading `RequestDisallowedByPolicy`

```
"statusMessage": {"error":{"code":"RequestDisallowedByPolicy","target":"examplenic1207",
  "message":"Resource `examplenic1207` was disallowed by policy. Policy identifiers:
  "policyAssignment":{"name":"Network interfaces should not have public IPs",
    "id":"/subscriptions/{sub}/providers/Microsoft.Authorization/policyAssignments/1111aa2222bb3333cc4444dd"} …
  "policyDefinition":{"name":…, "id":"…/policyDefinitions/<definition-name>"} …
```

(Microsoft's example, shortened.) The `name` shown is the **display name**; the real name, which the CLI needs, is the **last segment of each `id`**.

Then read the rule:

```
az policy definition show --name <definition-name>
az policy assignment show --name <assignment-name> --scope <scope-from-the-id>
```

The definition's `policyRule.if` says which property values are refused; the assignment's `parameters` fill in the allowed values (allowed locations, SKUs). If the message was lost, the **Activity log** of the target scope holds the same identifiers. A built-in definition lives at tenant scope (`/providers/Microsoft.Authorization/policyDefinitions/…`); a custom one at a management group or subscription (`--management-group <mg>` on `definition show`).

## Effects, in evaluation order

| Effect | What it does to your request |
|---|---|
| `disabled` | Nothing (checked first) |
| `append`, `modify` | **Change** the request before it reaches the provider: add tags, set properties, set `identity.type` on VMs. Your deployed resource may differ from your template |
| `deny` | Refuses create or update with **403**, before the resource provider sees it |
| `audit` | Allows, logs non-compliance |
| `manual` | Allows; compliance is attested |
| `auditIfNotExists` | Allows; after success, logs if a related resource is missing |
| `denyAction` | Refuses the named action, today only **DELETE**, with 403. Policy assignments, deny assignments, locks, deployment stacks and subscriptions are exempt |
| `deployIfNotExists` | After success, deploys a related resource (diagnostic settings, an agent: `reference/monitor/diagnostic-settings-and-data-collection.md`) using the **assignment's managed identity** |

`modify` and `deployIfNotExists` act through the assignment's identity, which needs the roles in the definition's `roleDefinitionIds` at the target scope. If remediation never happens, check that identity's role assignments. Existing resources are only fixed by a **remediation task**; a new assignment alone marks them non-compliant.

## Timing

| Event | Takes effect |
|---|---|
| New assignment | About 5 minutes |
| New or updated resource appears in compliance | About 15 minutes |
| Full compliance scan | Every 24 hours (or start an on-demand scan) |
| Tag-only `PATCH` | Only policies that inspect tags are evaluated |

## When a policy you expect doesn't act

| Symptom | Cause | Check |
|---|---|---|
| Resource created despite a deny policy, no Activity log entry | Assignment `enforcementMode` is `DoNotEnforce` | `az policy assignment show … --query enforcementMode` |
| Tag or location policy ignores the resource | Definition `mode` should be `indexed` for tags and location, `all` for everything else | `az policy definition show … --query mode` |
| Resource ignored | Its scope is in the assignment's `notScopes`, or an **exemption** (`waiver` or `mitigated`, possibly with `expiresOn`) covers it | `az policy assignment show … --query notScopes`; `az policy exemption list --scope <scope>` |
| Compliance shows old results | Evaluation hasn't run yet (timings above) | `az policy state list --resource <id> --top 5` |

## Exemptions

An exemption takes a resource or scope out of one assignment (or some definitions in an initiative) for a reason category, optionally until `expiresOn`: `az policy exemption create --name … --policy-assignment <assignment-id> --exemption-category waiver --scope <scope>`. Creating one needs policy-exemption write permission at that scope; agents should propose an exemption to their human, not create one to get past a deny.

## Policies that need an external evaluation (`--acquire-policy-token`)

In the policy API (stable 2025-03-01 and later, by its examples), a policy definition can carry `externalEvaluationEnforcementSettings`: before a write is allowed, an external endpoint (a change-approval system, for example) must have evaluated **that exact operation**. Its `missingTokenAction` (`Audit` or `Deny`) says what happens to a write that arrives without a **policy token**.

- The caller gets the token from `POST /subscriptions/{id}/providers/Microsoft.Authorization/acquirePolicyToken` with the operation's URI, method and body (and an optional `changeReference`), then sends the write with the token in the `x-ms-policy-external-evaluations` header. The token is bound to the request: its URI, API version and a hash of the payload.
- **Azure CLI 2.91** does this for you: every write command accepts `--acquire-policy-token` and `--change-reference <id>`. The CLI calls `acquirePolicyToken` (API 2025-11-01) with the same correlation ID, and fails with `Failed to acquire policy token, exception: …` or `No token returned. Response: …` when the endpoint refuses.
- A token response has a `result` (`Succeeded`, `Failed`), per-endpoint `results` with a `policyAction` and `message`, a `retryAfter` for retryable failures, and an `expiration`.

When a write is denied by such a policy and you didn't pass a token, retry with `--acquire-policy-token` (and the change reference your human gives you). If the token request itself fails, the external system's `message` is the reason: don't work around it.

## Next

Other refusal layers: `guides/identity/fix-access-denied.md`.


---
<!-- cuppy -->
You are reading one file. The same content is free over MCP at https://cuppy.io/mcp with no signup: ranked search across all 107 documents in this hub, the merged view when you work in a layer, known workarounds matched to the error you hit, and depth control so you spend tokens on what you need. Start with the `_hello` tool. How to connect: https://cuppy.io/azure/ Something wrong in this document? Report it with the `session feedback` tool on the same endpoint.
<!-- /cuppy -->
