Repository navigation
Description
🔴 Required Information
Describe the Bug:
ConnectionsClient._poll_operation() (used by ApplicationIntegrationToolset for connection entities and actions) has two problems:
- A failed operation is treated as success. A finished Connectors long-running operation carries either
responseorerror(google.longrunning.Operation). The loop only checksdone, and the callers then readresponse.jsonSchema/response.operations, falling back to{}/[]. So when the lookup fails, for example because of a mistyped entity or action name or a missing permission on the connection, the toolset builds without error and with no tools for that entity. With explicit operations it builds tools against an empty schema, and a failed action produces a tool with an empty display name. Nothing tells the developer why the agent can't reach the connector. - The wait is unbounded.
while not operation_done:has no deadline, so an operation that never finishes blocks toolset construction, and therefore agent startup, forever. bf4143a bounded each HTTP call in this client for exactly this reason ("an unavailable endpoint could block agent execution indefinitely"), but the polling loop around those calls is still open-ended.
It also sleeps one extra second after the operation is already done, which slows every entity and action lookup.
Steps to Reproduce:
pip install google-adk(reproduced onmain@ f33d492 / 2.9.0).- Run the script below. It builds a real
ApplicationIntegrationToolsetfor a connection whosegetEntityTypeoperation finishes witherror(entityAcountdoes not exist). HTTP is stubbed, so no GCP project is needed.
Expected Behavior:
Toolset construction fails with the operation's error message, and a stuck operation fails after a bounded wait.
Observed Behavior:
toolset built; tools: []
elapsed: 1.0s
Environment Details:
- ADK Library Version (pip show google-adk): 2.9.0 (
main@ f33d492) - Desktop OS: Windows 11
- Python Version (python -V): 3.12.10
Model Information:
- Are you using LiteLLM: No
- Which model is being used: N/A (toolset construction, no model call)
🟡 Optional Information
Minimal Reproduction Code:
import asyncio
from unittest import mock
from google.adk.tools.application_integration_tool import ApplicationIntegrationToolset
from google.adk.tools.application_integration_tool.clients.connections_client import ConnectionsClient
FAILED_OP = {
"name": "operations/op-1",
"done": True,
"error": {"code": 5, "message": "Entity type 'Acount' not found."},
}
def fake_get(url, headers=None, timeout=None):
resp = mock.MagicMock(status_code=200)
if url.endswith("?view=BASIC"):
resp.json.return_value = {"name": "projects/p/locations/us-central1/connections/sfdc",
"serviceDirectory": "sd", "host": ""}
elif "getEntityType" in url:
resp.json.return_value = {"name": "operations/op-1"}
else:
resp.json.return_value = FAILED_OP
return resp
mod = "google.adk.tools.application_integration_tool.clients.connections_client"
with mock.patch(f"{mod}._mtls_utils.get_api_endpoint", return_value="connectors.googleapis.com"), \
mock.patch.object(ConnectionsClient, "_get_access_token", return_value="token"), \
mock.patch(f"{mod}.requests.get", side_effect=fake_get):
toolset = ApplicationIntegrationToolset(
project="p", location="us-central1", connection="sfdc",
entity_operations={"Acount": []}, # typo for "Account"
)
print("toolset built; tools:", [t.name for t in asyncio.run(toolset.get_tools())])Suggested fix: in _poll_operation, raise ValueError with the operation's error message when a finished operation carries error. That's the error type the callers already document. Stop polling after a deadline with TimeoutError, and don't sleep once done is set. I have a PR ready with tests.
How often has this issue occurred?:
- Always (100%): any failed entity or action schema lookup.
Activity
sanketpatil06 commentedon Sep 18, 2026
Hi @1aifanatic,
You've accurately identified the critical issues in
ConnectionsClient._poll_operation(): the silent failure to propagate errors from Connectors long-running operations and the unbounded polling loop without a timeout.Thank you for the detailed analysis and for opening #7167. Team is reviewing reviewing the PR and test coverage.
1aifanatic commentedon Sep 18, 2026
Thank you @sanketpatil06! Glad the analysis and reproduction were helpful. Please let me know if any refinements are needed on the test coverage or timeout semantics as the team reviews #7167.
fix(application-integration): fail on errored or stuck schema operations
1aifanatic commentedon Sep 22, 2026
For reviewers, a summary of how #7167 fixes this. Three changes in
ConnectionsClient._poll_operation():google.longrunningoperation carries eitherresponseorerror, and the loop only checkeddone. The callers then readresponse.jsonSchema/response.operationswith{}/[]fallbacks, which is what turned a failed lookup into an empty toolset. A finished operation carryingerrornow raisesValueError("Operation <id> failed: <message>"), with the message the service returned.ValueErroris whatget_entity_schema_and_operations()andget_action_schema()already document, and it surfaces fromApplicationIntegrationToolset(...)construction, so a bad entity or a missing permission on the connection shows up at startup instead of as a silently tool-less agent.while not operation_done:had no deadline. It now stops after_DEFAULT_OPERATION_TIMEOUT_SECONDS(300 s) with aTimeoutError. Worth noting the individual HTTP calls in this client were already bounded at 30 s by bf4143a; it was only the loop around them that was open-ended, so a stuck operation still blocked agent startup forever.End to end, with
getEntityTypefinishing as{"done": true, "error": {"code": 5, "message": "Entity type 'Acount' not found."}}:Tests cover all three: a failed operation raises with the server's message, a never-finishing one raises
TimeoutErroronce the deadline passes (withtimemocked), and no sleep happens oncedoneis set. The repro script in the issue body needs no GCP project.One thing the PR deliberately does not change: 300 s is a guess at a safe ceiling for slow schema refreshes on large connectors. If the service team has a better number, I'm happy to change it.
adk-bot commentedon Sep 24, 2026
🚨 Automated Spam Detection Alert 🚨
@maintainers, a suspected spam comment was detected in this thread.
Reason:
1aifanatic commentedon Sep 27, 2026
@sanketpatil06 small housekeeping request: the
spamlabel here came from the automated alert above about a third-party comment, which has since been deleted. The report itself isn't spam; you confirmed it on Sept 18, and #7167 is the fix. Could you remove the label so it doesn't affect triage of the issue or the PR? Thanks!willie3838 commentedon Oct 29, 2026
Hey @1aifanatic thanks for contributing to this issue, we appreciate it. An internal team will be taking this over and credit your work!
fix: fail on connector schema operation error and bound poll wait