{"record":{"id":"cc2d27c6f93169fb","repo":"langchain-ai/deepagents","slug":"offload-server-returned-an-invalid-cancellation-ac","errorCode":null,"errorMessage":"Offload server returned an invalid cancellation acknowledgement.","messagePattern":"Offload server returned an invalid cancellation acknowledgement\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"libs/code/deepagents_code/client/remote_client.py","lineNumber":84,"sourceCode":"    \"\"\"Request cancellation and wait for the server's terminal acknowledgement.\n\n    Returns:\n        Server terminal status (`cancelled` or `finished`).\n\n    Raises:\n        RuntimeError: If the server returns an invalid acknowledgement.\n    \"\"\"\n    response = await asyncio.wait_for(\n        graph.client.http.post(\n            f\"/dcode/threads/{thread_id}/offload/{operation_id}/cancel\",\n            json={},\n        ),\n        timeout=_OFFLOAD_CANCEL_WAIT_SECONDS,\n    )\n    status = response.get(\"status\") if isinstance(response, dict) else None\n    if status not in {\"cancelled\", \"finished\"}:\n        msg = \"Offload server returned an invalid cancellation acknowledgement.\"\n        raise RuntimeError(msg)\n    return status\n\n\nasync def _await_offload_step[T](\n    awaitable: Awaitable[T],\n    *,\n    graph: Any,  # noqa: ANN401  # untyped RemoteGraph client\n    thread_id: str,\n    operation_id: str,\n) -> T:\n    \"\"\"Await one offload step and confirm server termination if cancelled.\n\n    Returns:\n        The awaited step's result.\n\n    Raises:\n        asyncio.CancelledError: After the server confirms the operation ended.\n    \"\"\"","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/code/deepagents_code/client/remote_client.py#L66-L102","documentation":"`_cancel_server_offload` asks the remote offload server to cancel an in-flight compaction and validates the acknowledgement; if the response `status` is neither `cancelled` nor `finished`, it raises `RuntimeError`. This guards against a server speaking an unexpected protocol or returning malformed cancellations.","triggerScenarios":"Calling `_await_offload_step` on a pending offload awaitable whose cancellation request returns a dict with an unknown `status` (or a non-dict response), after waiting up to `_OFFLOAD_CANCEL_WAIT_SECONDS`.","commonSituations":"Version mismatch between client and offload server (server returns new status values like `expired`); a proxy/gateway returning an HTML error page parsed oddly; server bugs acknowledging cancellation with an unexpected payload.","solutions":["Upgrade client and server to matching versions so cancellation statuses align.","Log the raw response to see the unexpected `status` value and add it to the accepted set if it is legitimately new.","Check network path for proxies that could mangle the JSON response body.","Retry the operation; if persistent, report a protocol bug to the server maintainers."],"exampleFix":"// before: strict two-status check\nif status not in {\"cancelled\", \"finished\"}: raise RuntimeError(msg)\n// after: accept documented new status\nif status not in {\"cancelled\", \"finished\", \"expired\"}: raise RuntimeError(msg)","handlingStrategy":"type-guard","validationCode":"def is_valid_cancel_ack(resp) -> bool:\n    return isinstance(resp, dict) and resp.get(\"status\") in {\"cancelled\", \"finished\"}\n# check before relying on the result\nif not is_valid_cancel_ack(response): reconcile_with_server()","typeGuard":"def is_valid_cancel_ack(resp: object) -> TypeGuard[dict]:\n    return isinstance(resp, dict) and resp.get(\"status\") in {\"cancelled\", \"finished\"}","tryCatchPattern":"try:\n    await _await_offload_step(pending)\nexcept RuntimeError as exc:\n    if \"invalid cancellation acknowledgement\" in str(exc):\n        log_raw_response_and_retry()","preventionTips":["Keep client and offload server versions in sync","Log raw cancellation responses to catch protocol drift early","Beware proxies/gateways altering JSON bodies"],"tags":["network","protocol","offload","remote"],"backgroundTag":"invalid-server-response","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}