Azure / Azure/azure-cli-extensions

[containerapp] az containerapp create --yaml injects null fields into PUT request body, causing HTTP 400 (System.Boolean conversion error)

Open
#9,729 6 comments 0 reactions 0 assignees View on GitHub
Auto-Assign bug ContainerApp customer-reported Service Attention
Dominant language
Python
Stars
454
Forks
1.7k
Avg merge
2d 19h
Merged PRs (30d)
64

Description

### Describe the bug

When using `az containerapp create --yaml `, the containerapp CLI extension serializes the
full internal model object and sends it as the HTTP PUT request body. All unset/optional fields
are included as `null` instead of being omitted.

This causes Azure Resource Manager (ARM) to fail during deserialization when it tries to convert
a `null` value into a non-nullable type such as `System.Boolean`. The result is an HTTP 400 error.

**Key offending null field confirmed via --debug:**

```json
{
"tags": null,
"extendedLocation": null,
"identity": null,
"managedBy": null,
"kind": null,
"properties": {
"configuration": {
"secrets": null,
"activeRevisionsMode": null,
"ingress": {
"fqdn": null,
"transport": null,
"traffic": null,
"allowInsecure": null, <- ARM tries to deserialize this as System.Boolean -> FAILS
"ipSecurityRestrictions": null,
"stickySessions": null,
"clientCertificateMode": null,
...
},
"dapr": null,
"runtime": null,
...
},
"template": {
"revisionSuffix": null,
"initContainers": null,
"containers": [
{
"command": null,
"args": null,
"env": null,
"volumeMounts": null,
"probes": null
}
],
"volumes": null,
"serviceBinds": null"
},
"workloadProfileName": null,
...
}
}
```

**`az containerapp update --yaml` works :** The update command uses HTTP PATCH and sends
only a sparse/diff body (without null fields), which succeeds. In this case, `update` requires the
resource to already exist and cannot be used for initial creation.

This bug has been confirmed on **both Global Azure (AzureCloud) and Azure China (AzureChinaCloud)**.

### Related command

```
az containerapp create --name --resource-group --yaml
```

### Errors

```
Bad Request({"type":"https://tools.ietf.org/html/rfc9110#section-15.5.1",
"title":"One or more validation errors occurred.",
"status":400,
"errors":{"$":["The JSON value could not be converted to System.Boolean.
Path: $ | LineNumber: 0 | BytePositionInLine: 4."]}})
```

### Issue script & Debug output

Minimal reproduction YAML (`capp-test.yaml`):

```yaml
location: eastus
name: capp-test
resourceGroup: my-rg
type: Microsoft.App/containerApps
properties:
managedEnvironmentId: /subscriptions//resourceGroups//providers/Microsoft.App/managedEnvironments/
configuration:
ingress:
external: true
targetPort: 80
template:
containers:
- name: capp-test
image: mcr.microsoft.com/k8se/quickstart:latest
resources:
cpu: 0.5
memory: 1Gi
scale:
minReplicas: 1
maxReplicas: 1
```

Reproduce:

```bash
az containerapp create --name capp-test --resource-group my-rg --yaml capp-test.yaml --debug
```

Debug log shows the PUT request body contains dozens of `null` fields, including
`"allowInsecure": null`, which ARM cannot deserialize as `System.Boolean`.

### Expected behavior

The CLI extension should omit null/unset fields from the PUT request body (or use JSON merge
patch semantics), so that ARM only receives fields that are explicitly set in the YAML.

Workaround that works today: use `az deployment group create --template-file xxx.bicep` (Bicep
or ARM JSON), which does not have this serialization issue.

### Environment Summary

az --version
azure-cli 2.84.0

core 2.84.0
telemetry 1.1.0

Extensions:
containerapp 1.3.0b4
resource-graph 2.1.1

Dependencies:
msal 1.35.0b1
azure-mgmt-resource 24.0.0

Python location 'C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\python.exe'
Config directory 'C:\Users\xxx\.azure'
Extensions directory 'C:\Users\xxx\.azure\cliextensions'

Python (Windows) 3.13.11 (tags/v3.13.11:6278944, Dec 5 2025, 16:17:02) [MSC v.1944 32 bit (Intel)]

Legal docs and information: aka.ms/AzureCliLegal

Your CLI is up-to-date.

### Additional context

- `az containerapp update --yaml` (PATCH) works correctly because it sends a sparse body
- `az deployment group create --template-file` (Bicep/ARM JSON) works correctly
- The `--yaml` input flag is unique to `az containerapp` commands; other services
(az vm, az aks, az deployment) do NOT support `--yaml` as an input format

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.