Azure / Azure/azure-sdk-for-python

[Document Intelligence] queryFields against on-prem Layout container returns 202 then pins the operation at status=running forever (no terminal error)

Open
#47,943 2 comments 1 reaction 1 assignee Claimed by @bojunehsu View on GitHub
Client customer-reported Document Intelligence needs-team-attention question
Dominant language
Python
Stars
5.6k
Forks
3.4k
Avg merge
1d 21h
Merged PRs (30d)
193

Description

- **Package Name**: azure-ai-documentintelligence
- **Package Version**: 1.0.2 (azure-core 1.41.0)
- **Operating System**: macOS (arm64); container image `linux/amd64` (`layout-4.0`)
- **Python Version**: 3.14.6

**Describe the bug**

Sending an analyze request with the `queryFields` add-on to an on-premises (connected)
Document Intelligence **Layout container** never completes. The initial `POST …:analyze`
returns `202 Accepted`, but the operation then stays at `"status": "running"` **indefinitely**
and never transitions to `succeeded` or `failed`. Because `poller.result()` has no overall
deadline, the client hangs forever with **no exception raised**.

Two controls prove the request itself is valid:
- The same request **without** `queryFields` succeeds against the same container in seconds.
- The same request **with** `queryFields` succeeds against the **cloud** endpoint in seconds.

This implies the query-fields add-on isn't implemented in the container image — but instead of
failing the operation with a terminal error, the container leaves it pinned at `running`. The
container is idle (~2% CPU) throughout, so this is not a latency/throughput issue.

**To Reproduce**

Steps to reproduce the behavior:

1. Run the connected Layout container:
`mcr.microsoft.com/azure-cognitive-services/form-recognizer/layout-4.0` (API `2024-11-30`),
with valid `Eula`/`billing`/`apiKey` (`GET /status` returns 200).
2. Call `begin_analyze_document` with the query-fields add-on:

```python
import asyncio, io
from azure.ai.documentintelligence.aio import DocumentIntelligenceClient
from azure.ai.documentintelligence.models import DocumentAnalysisFeature
from azure.core.credentials import AzureKeyCredential

ENDPOINT = "http://localhost:5000" # container does not validate the key

async def main():
async with DocumentIntelligenceClient(ENDPOINT, AzureKeyCredential("placeholder")) as client:
with open("sample.pdf", "rb") as f:
body = f.read()
poller = await client.begin_analyze_document(
"prebuilt-layout",
body=io.BytesIO(body),
features=[DocumentAnalysisFeature.QUERY_FIELDS],
query_fields=["VendorName", "InvoiceTotal"],
)
result = await poller.result() # never returns; no exception
print(result)

asyncio.run(main())
```

3. Observe that the call never returns and never raises.

The same behavior at the HTTP level (isolates the SDK):

```console
$ curl -s -D - -o /dev/null -X POST \
"http://localhost:5000/documentintelligence/documentModels/prebuilt-layout:analyze?api-version=2024-11-30&features=queryFields&queryFields=VendorName,InvoiceTotal" \
-H "Content-Type: application/octet-stream" --data-binary @sample.pdf
HTTP/1.1 202 Accepted
Operation-Location: http://localhost:5000/documentintelligence/documentModels/prebuilt-layout/analyzeResults/?api-version=2024-11-30

$ curl -s "http://localhost:5000/documentintelligence/documentModels/prebuilt-layout/analyzeResults/?api-version=2024-11-30"
{"status":"running", ...}
# polled repeatedly over minutes -> always "running", never "succeeded"/"failed"
```

**Expected behavior**

The operation transitions to `"status": "failed"` with a terminal error (e.g. `InvalidArgument`
or a "feature not supported by this container" message), so `poller.result()` raises
`HttpResponseError` promptly instead of hanging.

**Screenshots**

N/A — text output shown above (`202 Accepted` followed by an indefinite `"status": "running"`).

**Additional context**

A/B/C evidence:

| Request | Backend | Result |
| --- | --- | --- |
| `prebuilt-layout`, no add-on | on-prem container | ✅ succeeds in seconds |
| `prebuilt-layout` + `queryFields` | on-prem container | ⌛ `status=running` forever, no error |
| `prebuilt-layout` + `queryFields` | cloud (Azure) | ✅ succeeds in seconds, returns fields |

Root cause appears to be the async LRO contract: the `POST` validates only the request envelope
(`queryFields` is a valid parameter in the `2024-11-30` contract the container shares with cloud),
so it returns `202` and queues an operation; the container then reaches the query-fields stage,
which isn't shipped in the image, and leaves the operation at `running` rather than transitioning
it to `failed`. Each poll is itself a valid `200 {"status":"running"}`, so nothing raises.

Requests:
1. **Service/container:** fail the operation with a terminal error when an unsupported add-on is
requested, instead of leaving it at `running`.
2. **Docs:** explicitly document which add-on capabilities (`queryFields`, `keyValuePairs`, …)
are supported in the containers vs. cloud — this is currently undocumented.
3. **SDK (optional):** consider a documented default overall deadline for the analyze poller, or
clearer guidance, so a service-side operation stuck at `running` doesn't manifest as a silent,
unbounded client hang.

Possibly related (not duplicates): #43085 (error handling), #42520 (LRO examples/timeouts),
#42152 (poller blocks loop), #43114 (`polling_interval` not respected), #36841 (error messaging
for unsupported inputs), #44449 (container + analyze, but 100% CPU — opposite symptom).

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.