iflytek/astron-agent · error · RuntimeError
artifact_snapshot_failed
Error message
artifact_snapshot_failed
What it means
Raised in _scan_artifact_candidates when the artifact-scan helper script executed inside the E2B sandbox exits with a non-zero exit code. The helper walks the output directory collecting candidate artifact files; a non-zero exit means the scan could not complete reliably, so artifact collection aborts with 'artifact_snapshot_failed'.
Solutions
- Inspect the sandbox command result (stderr may be suppressed by 2>/dev/null) — rerun the scan command manually inside the sandbox without suppression to see the real error.
- Verify python3 exists in the sandbox image at /usr/local/bin:/usr/bin:/bin and install it in the image if absent.
- Increase the command timeout passed to _collect_artifacts if large output directories cause timeouts.
- Retry the sandbox run; transient sandbox state (e.g. killed process) often resolves on a fresh execution.
Example fix
// before (debug) PATH=... python3 -c '<helper>' ... 2>/dev/null | head -c N // after (diagnose) # run inside the sandbox without 2>/dev/null to see the helper's error output
Defensive patterns
Strategy: retry
Validate before calling
def sandbox_supports_scan(sandbox) -> bool:
# ensure python3 exists before running helper-based commands
r = sandbox.commands.run("command -v python3", timeout=10, user="root")
return int(getattr(r, "exit_code", 1)) == 0 Type guard
def scan_result_ok(result) -> bool:
return result is not None and int(getattr(result, "exit_code", 1) or 0) == 0 and bool(str(getattr(result, "stdout", "") or "").strip()) Try / catch
for attempt in range(2):
try:
candidates = await _scan_artifact_candidates(sandbox, output_dir, excluded, timeout_s)
break
except RuntimeError as e:
if str(e) == "artifact_snapshot_failed" and attempt == 0:
logger.warning("artifact scan failed once; retrying with fresh command")
continue
logger.warning("artifact collection skipped: snapshot scan failed")
candidates = [] Prevention
- Verify the sandbox image ships python3 and coreutils at the hardcoded PATH entries.
- Size timeout_seconds to the largest expected output tree.
- Test artifact collection with a skill that produces many/large outputs before enabling artifacts in production.
When it happens
Trigger: sandbox.commands.run returns exit_code != 0 for the scan command — e.g. python3 missing or failing inside the sandbox, the helper crashing, the `head -c` pipe closing early, or command timeout causing abnormal termination.
Common situations: Sandbox image lacks python3 on PATH (command hardcodes PATH=/usr/local/bin:/usr/bin:/bin); output directory deleted mid-run; sandbox resource exhaustion; timeout_seconds too small for large output trees.
Related errors
- 21600
- 21600
- Artifact upload configuration is unavailable
- Artifact upload credential is missing or invalid
- ARTIFACT_UPLOAD_FAILED_ERROR
AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12).
Data as JSON: /api/errors/b6224999792cc940.
Report an issue: GitHub.
Appendix: source
Thrown at core/agent/service/plugin/skill_sandbox.py:333
timeout_seconds: int,
) -> list[dict[str, Any]]:
command = _bounded_helper_command(
_ARTIFACT_SCAN_HELPER,
[
output_dir,
str(MAX_ARTIFACT_FILES_PER_RUN + 1),
json.dumps(sorted(excluded_paths), ensure_ascii=True),
str(MAX_ARTIFACT_RELATIVE_PATH_BYTES),
],
MAX_ARTIFACT_SCAN_OUTPUT_BYTES,
)
result = await sandbox.commands.run(
command,
timeout=timeout_seconds,
user="root",
)
if int(getattr(result, "exit_code", 0) or 0) != 0:
raise RuntimeError(ARTIFACT_SNAPSHOT_ERROR)
stdout = str(getattr(result, "stdout", "") or "")
if len(stdout.encode("utf-8", "surrogateescape")) > MAX_ARTIFACT_SCAN_OUTPUT_BYTES:
raise RuntimeError(ARTIFACT_SNAPSHOT_ERROR)
try:
payload = json.loads(stdout)
except (TypeError, ValueError):
raise RuntimeError(ARTIFACT_SNAPSHOT_ERROR) from None
if not isinstance(payload, list) or len(payload) > MAX_ARTIFACT_FILES_PER_RUN + 1:
raise RuntimeError(ARTIFACT_SNAPSHOT_ERROR)
return [item for item in payload if isinstance(item, dict)]
async def _read_bounded_snapshot(
sandbox: Any,
file_path: str,
max_bytes: int,
timeout_seconds: int,
) -> tuple[bytes, bool]:View on GitHub (pinned to 5e758547a8)