iflytek/astron-agent · error · IOException

sandbox-exec failed: HTTP

Error message

sandbox-exec failed: HTTP 

What it means

executeSandbox posts to the sandbox-exec HTTP endpoint using an OkHttp client configured with no redirects and a 120s call timeout. When the sandbox service answers with a non-2xx status, the method throws an IOException with only the status code (never the response body, deliberately avoiding leaking sensitive details). It means the sandbox execution request was rejected or failed server-side.

Solutions

  1. Check that the sandbox service is up and reachable at the configured URL (curl the health endpoint).
  2. Inspect sandbox service logs for the corresponding request to learn the real error (the exception intentionally hides the body).
  3. Verify sandbox credentials/auth and that the request payload meets sandbox input constraints.
  4. Check gateway/proxy settings for timeouts (120s callTimeout) and body-size limits between console backend and sandbox.

Example fix

// before
// executeSandbox throws bare "sandbox-exec failed: HTTP 502"
try {
    String out = skillRuntimeToolService.runSkill(skillId, input);
} catch (IOException e) {
    // e.getMessage() only has the status code
}
// after
try {
    String out = skillRuntimeToolService.runSkill(skillId, input);
} catch (IOException e) {
    log.error("sandbox exec failed; verify sandbox service health/config", e);
    throw new BusinessException(ResponseEnum.SANDBOX_EXEC_FAILED); // user-facing message
}
Defensive patterns

Strategy: try-catch

Validate before calling

boolean sandboxHealthy = httpGet(sandboxUrl + "/health").code() == 200;
if (!sandboxHealthy) {
    throw new IllegalStateException("Sandbox service unavailable");
}

Try / catch

try {
    String result = skillRuntimeToolService.runSkill(skillId, input);
} catch (IOException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("sandbox-exec failed: HTTP")) {
        int status = Integer.parseInt(e.getMessage().substring(e.getMessage().lastIndexOf(' ') + 1));
        // retry on 5xx only; surface 4xx to the user
    }
}

Prevention

When it happens

Trigger: The sandbox service returns HTTP 4xx/5xx to executeSandbox — e.g. sandbox container not running, auth rejection, payload rejected, or gateway 502/503 — while a skill is being run via runSkill.

Common situations: Sandbox deployment down or misconfigured (wrong sandbox URL in config); sandbox returned 401/403 due to expired credentials; 413 for oversized skill payloads; 504 when skill execution exceeded sandbox limits; network proxy or service mesh blocking the call.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12). Data as JSON: /api/errors/c09c8e3f19ec9ded. Report an issue: GitHub.

Appendix: source

Thrown at console/backend/hub/src/main/java/com/iflytek/astron/console/hub/service/chat/springai/SkillRuntimeToolService.java:95

        String signature = runtimeCredentialTokenProvider.signExecutionRequest(
                timestamp, requestBody);
        Request request = new Request.Builder()
                .url(url)
                .post(RequestBody.create(requestBody, JSON_MEDIA_TYPE))
                .addHeader("Content-Type", "application/json")
                .addHeader(
                        "X-Skill-Sandbox-Execution-Timestamp",
                        String.valueOf(timestamp))
                .addHeader("X-Skill-Sandbox-Execution-Signature", signature)
                .build();
        OkHttpClient client = httpClient.newBuilder()
                .callTimeout(Duration.ofSeconds(120))
                .followRedirects(false)
                .followSslRedirects(false)
                .build();
        try (Response response = client.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                throw new IOException("sandbox-exec failed: HTTP " + response.code());
            }
            ResponseBody respBody = response.body();
            return respBody == null
                    ? ""
                    : decodeText(
                            readBounded(respBody, maxSandboxResponseBytes, "Sandbox response"),
                            respBody);
        }
    }

    /** Download a text resource (SKILL.md or a referenced file) from a presigned URL. */
    public String downloadText(String url) throws IOException {
        validateLimit(maxResourceBytes, "Skill resource");
        validateResourceUrl(url);
        Request request;
        try {
            request = new Request.Builder().url(url).get().build();
        } catch (IllegalArgumentException exception) {

View on GitHub (pinned to 5e758547a8)