iflytek/astron-agent · warning · IOException
Skill resource download returned empty body
Error message
Skill resource download returned empty body
What it means
After a successful (2xx) response, downloadText checks that a ResponseBody exists; a 2xx response with a null body (possible with 204/205 or degenerate responses) is treated as a failed download and throws "Skill resource download returned empty body". Skill resources must carry actual text content, so an empty body is invalid.
Solutions
- Verify the resource file was actually uploaded and is non-empty in the skill registry/storage.
- Check proxy/CDN configuration that may strip or truncate response bodies.
- Point the skill manifest at the correct resource URL — a 204 from a wrong path mimics an empty success.
- Treat this as a publish-time data error: validate skill resources are non-empty when the skill is saved.
Example fix
// before
// zero-byte resource uploaded; downloadText throws at runtime
storageClient.put(bucket, key, new byte[0]);
// after
byte[] data = Files.readAllBytes(path);
if (data.length == 0) {
throw new IllegalArgumentException("Skill resource file is empty");
}
storageClient.put(bucket, key, data); Defensive patterns
Strategy: try-catch
Validate before calling
Response head = httpHead(url);
boolean bodyExpected = head.code() == 200 && head.body() != null && head.headers().get("Content-Length") != null;
if (!bodyExpected) {
throw new IllegalStateException("Resource has no body");
} Try / catch
try {
String content = service.downloadText(url, limit);
} catch (IOException e) {
if ("Skill resource download returned empty body".equals(e.getMessage())) {
// treat as corrupt/missing resource; re-upload it
}
} Prevention
- Reject zero-byte skill resource uploads at publish time.
- Verify resource integrity (size/checksum) after uploading to storage.
- Check proxies/caches for body-stripping configurations in test environments.
When it happens
Trigger: The resource endpoint returns 204 No Content, 205 Reset Content, or a 2xx with zero-length/absent body while downloadText reads a skill resource.
Common situations: The resource server (or an intermediate cache/proxy) stripped the body; uploading a zero-byte skill resource file; a misconfigured static file server returning 204 for missing files; a mock/stub server used in a test environment returning empty success responses.
Related errors
- Skill resource download failed: HTTP
- REPO_KNOWLEDGE_DOWNLOAD_FAILED
- sandbox-exec failed: HTTP
- exceeds size limit
- SYSTEM_ERROR
AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12).
Data as JSON: /api/errors/6b967d292c138dc2.
Report an issue: GitHub.
Appendix: source
Thrown at console/backend/hub/src/main/java/com/iflytek/astron/console/hub/service/chat/springai/SkillRuntimeToolService.java:127
validateResourceUrl(url);
Request request;
try {
request = new Request.Builder().url(url).get().build();
} catch (IllegalArgumentException exception) {
throw new IOException("Skill resource URL is not allowed");
}
OkHttpClient client = httpClient.newBuilder()
.callTimeout(Duration.ofSeconds(30))
.followRedirects(false)
.followSslRedirects(false)
.build();
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) {
throw new IOException("Skill resource download failed: HTTP " + response.code());
}
ResponseBody body = response.body();
if (body == null) {
throw new IOException("Skill resource download returned empty body");
}
return decodeText(readBounded(body, maxResourceBytes, "Skill resource"), body);
}
}
private byte[] readBounded(ResponseBody body, long limit, String description)
throws IOException {
validateLimit(limit, description);
long contentLength = body.contentLength();
if (contentLength > limit) {
throw new IOException(description + " exceeds size limit");
}
int readLimit = Math.toIntExact(limit + 1);
try (InputStream input = body.byteStream()) {
byte[] bytes = input.readNBytes(readLimit);
if (bytes.length > limit) {
throw new IOException(description + " exceeds size limit");
}View on GitHub (pinned to 5e758547a8)