{"record":{"id":"b6224999792cc940","repo":"iflytek/astron-agent","slug":"artifact-snapshot-failed","errorCode":null,"errorMessage":"artifact_snapshot_failed","messagePattern":"artifact_snapshot_failed","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"core/agent/service/plugin/skill_sandbox.py","lineNumber":333,"sourceCode":"    timeout_seconds: int,\n) -> list[dict[str, Any]]:\n    command = _bounded_helper_command(\n        _ARTIFACT_SCAN_HELPER,\n        [\n            output_dir,\n            str(MAX_ARTIFACT_FILES_PER_RUN + 1),\n            json.dumps(sorted(excluded_paths), ensure_ascii=True),\n            str(MAX_ARTIFACT_RELATIVE_PATH_BYTES),\n        ],\n        MAX_ARTIFACT_SCAN_OUTPUT_BYTES,\n    )\n    result = await sandbox.commands.run(\n        command,\n        timeout=timeout_seconds,\n        user=\"root\",\n    )\n    if int(getattr(result, \"exit_code\", 0) or 0) != 0:\n        raise RuntimeError(ARTIFACT_SNAPSHOT_ERROR)\n    stdout = str(getattr(result, \"stdout\", \"\") or \"\")\n    if len(stdout.encode(\"utf-8\", \"surrogateescape\")) > MAX_ARTIFACT_SCAN_OUTPUT_BYTES:\n        raise RuntimeError(ARTIFACT_SNAPSHOT_ERROR)\n    try:\n        payload = json.loads(stdout)\n    except (TypeError, ValueError):\n        raise RuntimeError(ARTIFACT_SNAPSHOT_ERROR) from None\n    if not isinstance(payload, list) or len(payload) > MAX_ARTIFACT_FILES_PER_RUN + 1:\n        raise RuntimeError(ARTIFACT_SNAPSHOT_ERROR)\n    return [item for item in payload if isinstance(item, dict)]\n\n\nasync def _read_bounded_snapshot(\n    sandbox: Any,\n    file_path: str,\n    max_bytes: int,\n    timeout_seconds: int,\n) -> tuple[bytes, bool]:","sourceCodeStart":315,"sourceCodeEnd":351,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/core/agent/service/plugin/skill_sandbox.py#L315-L351","documentation":"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'.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before (debug)\nPATH=... python3 -c '<helper>' ... 2>/dev/null | head -c N\n// after (diagnose)\n# run inside the sandbox without 2>/dev/null to see the helper's error output","handlingStrategy":"retry","validationCode":"def sandbox_supports_scan(sandbox) -> bool:\n    # ensure python3 exists before running helper-based commands\n    r = sandbox.commands.run(\"command -v python3\", timeout=10, user=\"root\")\n    return int(getattr(r, \"exit_code\", 1)) == 0","typeGuard":"def scan_result_ok(result) -> bool:\n    return result is not None and int(getattr(result, \"exit_code\", 1) or 0) == 0 and bool(str(getattr(result, \"stdout\", \"\") or \"\").strip())","tryCatchPattern":"for attempt in range(2):\n    try:\n        candidates = await _scan_artifact_candidates(sandbox, output_dir, excluded, timeout_s)\n        break\n    except RuntimeError as e:\n        if str(e) == \"artifact_snapshot_failed\" and attempt == 0:\n            logger.warning(\"artifact scan failed once; retrying with fresh command\")\n            continue\n        logger.warning(\"artifact collection skipped: snapshot scan failed\")\n        candidates = []","preventionTips":["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."],"tags":["sandbox","subprocess","artifacts"],"backgroundTag":"command-not-found","analyzedSha":"5e758547a83371a5a4b29dadf4ac03e8dd527635","analyzedAt":"2026-09-12T08:03:51.356Z","contentChangedAt":"2026-09-12T08:03:51.356Z","schemaVersion":2},"datasetVersion":"2026-09-19T12:17:13.211Z"}