alibaba/spring-ai-alibaba · error · WebFetchException
Failed after attempts
Error message
Failed after attempts
What it means
After exhausting all fetch attempts in fetchHtmlWithRetry, WebFetchTool throws WebFetchException('Failed after N attempts'). The no-cause branch (line 270) fires when the loop ended with lastException == null — every attempt returned normally per the catch structure but no usable response was produced — or conceptually marks the generic exhaustion message. It means the URL could not be fetched within the configured retry budget.
Source
Thrown at spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/tools/WebFetchTool.java:270
return response;
}
catch (WebFetchException e) {
lastException = e;
if (e.getCause() instanceof InterruptedException) {
throw e;
}
logger.warn("Fetch attempt {} failed for URL: {}: {}", attempt + 1, url, e.getMessage());
attempt++;
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new WebFetchException("Retry interrupted", e);
}
}
if (lastException == null) {
throw new WebFetchException("Failed after " + (this.maxRetries + 1) + " attempts", null);
}
else if (lastException instanceof WebFetchException) {
throw new WebFetchException("Failed after " + (this.maxRetries + 1) + " attempts", lastException);
}
else {
throw new WebFetchException(
"Failed after " + (this.maxRetries + 1) + " attempts: " + lastException.getMessage(),
lastException);
}
}
private HttpResponse<String> fetchHtml(String url) {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.timeout(DEFAULT_REQUEST_TIMEOUT)
.header("User-Agent", USER_AGENT)
.header("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
.header("Accept-Language", "en-US,en;q=0.5")View on GitHub (pinned to f82da0b50f)
Solutions
- Verify the URL is reachable from the host with curl or a browser.
- Increase maxRetries via the Builder for flaky targets.
- Inspect the chained cause (getCause()) to find the real network failure.
- Add connectivity/proxy configuration (HTTP_PROXY, VPN, firewall rules) for the runtime.
Example fix
// before
WebFetchTool tool = WebFetchTool.builder(chatClient).build();
// after
WebFetchTool tool = WebFetchTool.builder(chatClient)
.maxRetries(3)
.build(); Defensive patterns
Strategy: retry
Validate before calling
URI uri = URI.create(url);
if (uri.getScheme() == null ||
!(uri.getScheme().equals("http") || uri.getScheme().equals("https"))) {
throw new IllegalArgumentException("invalid fetch URL: " + url);
} Try / catch
try {
String html = webFetchTool.fetch(url);
} catch (WebFetchException e) {
log.warn("fetch exhausted: {} cause={}", e.getMessage(), e.getCause());
return fallbackContent(url);
} Prevention
- Verify URL reachability (curl/DNS) before wiring it into the agent
- Configure an adequate maxRetries for flaky targets
- Ensure outbound network/proxy access from the runtime environment
When it happens
Trigger: Calling WebFetchTool on a URL where all maxRetries+1 attempts fail, and the final recorded exception is null or a WebFetchException already carrying its own cause.
Common situations: Fetching an unreachable or DNS-failing host; misconfigured maxRetries=0 with a flaky network; a proxy or firewall blocking egress from the runtime environment; URL temporarily returning errors until retries run out.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- Failed after attempts:
- Fetch attempt {} failed for URL: {}: {}
- Oauth2CallError
- failed to create index
- Retry interrupted
AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09).
Data as JSON: /api/errors/61090a6374ae8e26.
Report an issue: GitHub.