From c4be43904f7bb17dfbecaf7802513061373f97af Mon Sep 17 00:00:00 2001 From: Paul Cornell Date: Thu, 31 Jul 2025 10:27:46 -0700 Subject: [PATCH 1/2] Python SDK: new classes for more robust error handling --- api-reference/workflow/errors.mdx | 99 +++++++++++++++++++++++++++++++ docs.json | 1 + 2 files changed, 100 insertions(+) create mode 100644 api-reference/workflow/errors.mdx diff --git a/api-reference/workflow/errors.mdx b/api-reference/workflow/errors.mdx new file mode 100644 index 00000000..91ba3d57 --- /dev/null +++ b/api-reference/workflow/errors.mdx @@ -0,0 +1,99 @@ +--- +title: Errors +--- + +For the [Unstructured Python SDK](/api-reference/workflow/overview#unstructured-python-sdk), +the [Unstructured Workflow Endpoint](/api-reference/workflow/overview) returns errors primarily through +the `UnstructuredClientError` and `HTTPValidationError` classes. Less common errors are returned through the following classes: + +- `httpx.RequestError`, the base class for request errors. +- `httpx.ConnectError`, for HTTP connection request errors. +- `httpx.TimeoutException`, for HTTP request timeout errors. +- `ServerError` (inherited from `UnstructuredClientError`), for server-side errors. +- `ResponseValidationError` (inherited from `UnstructuredClientError`), for type mismatches between the response data and the expected Pydantic model. + +Each of the preceding classes has the following members: + +| Member | Type | Description | +|--------|------|-------------| +| `message` | `str` | The eror message. | +| `status_code` | `int` | The HTTP response status code, for example `401`. | +| `headers` | `httpx.Headers` | A collection of HTTP response headers. | +| `body` | `str` | The HTTP body. This can be an empty string if no body is returned. | +| `raw_response` | `httpx.Response` | The raw HTTP response. + +The following example shows how to handle the preceding errors. In this example, +a required Unstructured API key is intentionally commented out of the code, so that a +`401 Unauthorized` error is intentionally thrown. + +```python +import os + +from unstructured_client import UnstructuredClient +from unstructured_client.models.operations import ListWorkflowsRequest +from unstructured_client.models.errors import ( + UnstructuredClientError, + HTTPValidationError +) +from unstructured_client.models.errors.servererror import ServerError +from unstructured_client.models.errors.responsevalidationerror import ResponseValidationError +import httpx + +try: + client = UnstructuredClient( + # For example, intentionally leave out the API key to intentionally throw an error. + # api_key_auth=os.getenv("UNSTRUCTURED_API_KEY") + ) + + response = client.workflows.list_workflows( + request=ListWorkflowsRequest() + ) + + print(f"Found {len(response.response_list_workflows)} workflows.") + +except HTTPValidationError as e: + print("Validation error (HTTP 422):", e) +except ServerError as e: + print("Server error (HTTP 5XX):", e) +except ResponseValidationError as e: + print("Response validation/type mismatch:", e) +except UnstructuredClientError as e: + # This catches any other UnstructuredClientError not already caught above. + # This and all of the other error classes in this example expose the following members: + print("Other Unstructured client error:") + print(f"Message: {e.message}") + print(f"Status code: {e.status_code}") + print(f"Body: {e.body}") + print(f"Raw response: {e.raw_response}") + print(f"Headers:") + + for header in e.headers.raw: + key = header[0].decode('utf-8') + value = header[1].decode('utf-8') + print(f" {key}: {value}") + +except httpx.ConnectError as e: + print("HTTP connection error:", e) +except httpx.TimeoutException as e: + print("HTTP timeout error:", e) +except httpx.RequestError as e: + # This catches catch-all network errors from HTTP not already caught above. + print("Other HTTPX request error:", e) +except Exception as e: + # Optional: this catches any other unforeseen errors. + print("Unexpected error:", e) +``` + +The results of running the preceding code are similar to the following: + +```text +Message: API error occurred: Status 401. Body: {"detail":"API key is missing, please provide an API key in the header."} +Status code: 401 +Body: {"detail":"API key is missing, please provide an API key in the header."} +Raw response: +Headers: + date: + server: + content-length: 73 + content-type: application/json +``` \ No newline at end of file diff --git a/docs.json b/docs.json index 68afa20d..5065a334 100644 --- a/docs.json +++ b/docs.json @@ -202,6 +202,7 @@ }, "api-reference/workflow/workflows", "api-reference/workflow/jobs", + "api-reference/workflow/errors", { "group": "Endpoint Playground", "openapi": "https://platform.unstructuredapp.io/openapi.json" From 4215f845f5841e68d0d8310bc0caacd00943d5b2 Mon Sep 17 00:00:00 2001 From: Paul Cornell Date: Thu, 31 Jul 2025 11:25:15 -0700 Subject: [PATCH 2/2] Incorporated feedback: UnstructuredClientError is the base exception --- api-reference/workflow/errors.mdx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/api-reference/workflow/errors.mdx b/api-reference/workflow/errors.mdx index 91ba3d57..d36fc808 100644 --- a/api-reference/workflow/errors.mdx +++ b/api-reference/workflow/errors.mdx @@ -4,7 +4,8 @@ title: Errors For the [Unstructured Python SDK](/api-reference/workflow/overview#unstructured-python-sdk), the [Unstructured Workflow Endpoint](/api-reference/workflow/overview) returns errors primarily through -the `UnstructuredClientError` and `HTTPValidationError` classes. Less common errors are returned through the following classes: +the `UnstructuredClientError` class (the base class for all errors raised by the Unstructured Python SDK) and +the `HTTPValidationError` class (inherited from `UnstructuredClientError`). Less common errors are returned through the following classes: - `httpx.RequestError`, the base class for request errors. - `httpx.ConnectError`, for HTTP connection request errors.