iflytek/astron-agent · warning · RuntimeError
ARTIFACT_UPLOAD_FAILED_ERROR
Error message
ARTIFACT_UPLOAD_FAILED_ERROR
What it means
CodeArtifactUploader.upload() posts an artifact file to the internal upload endpoint and strictly validates the result: HTTP status must be 2xx AND the JSON payload must be a dict with an integer code == 0 and a dict 'data'. Any deviation (non-2xx, redirect, non-JSON body, business error code, malformed payload) raises RuntimeError('artifact_upload_failed'). Callers (_upload_artifact) catch this and mark the artifact's upload_error field.
Solutions
- Verify SKILL_SANDBOX_ARTIFACT_UPLOAD_URL is reachable and returns the expected {code:0, data:{...}} envelope (curl the endpoint).
- Check SKILL_SANDBOX_ARTIFACT_UPLOAD_TOKEN (or *_FILE) is set and >= 32 characters; confirm it is accepted (no 401/403).
- Confirm the file is under 20MB and total uploads under 100MB for the run; skip or split oversized artifacts.
- Retry transient network failures; check server logs for the business error code returned in the payload.
Example fix
// before
payload = await response.json(content_type=None)
return payload # crashes later or hides business errors
// after
if not 200 <= response.status < 300:
logger.warning("artifact upload http status={}", response.status)
raise RuntimeError(ARTIFACT_UPLOAD_FAILED_ERROR)
payload = await response.json(content_type=None)
if not (isinstance(payload, dict) and payload.get("code") == 0):
raise RuntimeError(ARTIFACT_UPLOAD_FAILED_ERROR)
return payload["data"] Defensive patterns
Strategy: retry
Validate before calling
uploader = CodeArtifactUploader(sandbox_config)
if not uploader.is_configured():
# skip artifact upload instead of failing the run
return Type guard
def is_valid_upload_payload(p: object) -> bool:
return (isinstance(p, dict) and isinstance(p.get("code"), int)
and not isinstance(p.get("code"), bool) and p["code"] == 0
and isinstance(p.get("data"), dict)) Try / catch
try:
await uploader.upload(name, data, ctype)
except RuntimeError:
artifact["upload_error"] = "artifact_upload_failed" # degrade gracefully Prevention
- Check is_configured() before attempting uploads.
- Enforce the 20MB per-file / 100MB total limits client-side before upload.
- Verify upload URL and token env vars in deployment checks.
When it happens
Trigger: Upload POST returns non-2xx status or redirects; response body is not JSON; payload.code != 0 or code is a bool/missing; payload.data is missing or not a dict; aiohttp network/timeout error during the 60s-limited request.
Common situations: Wrong SKILL_SANDBOX_ARTIFACT_UPLOAD_URL or service down; artifact upload token missing/shorter than 32 chars causing 401/403; file exceeds 20MB per-file or 100MB total limits rejected by server; transient network failure.
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/b18c24ff281ec589.
Report an issue: GitHub.
Appendix: source
Thrown at core/workflow/engine/nodes/code/executor/e2b/e2b_executor.py:794
headers=headers,
allow_redirects=False,
) as response:
if not 200 <= response.status < 300:
raise ValueError
response.raise_for_status()
payload = await response.json(content_type=None)
code = payload.get("code") if isinstance(payload, dict) else None
data = payload.get("data") if isinstance(payload, dict) else None
if (
isinstance(code, bool)
or not isinstance(code, int)
or code != 0
or not isinstance(data, dict)
):
raise ValueError
return data
except Exception:
raise RuntimeError(ARTIFACT_UPLOAD_FAILED_ERROR) from None
View on GitHub (pinned to 5e758547a8)