{"record":{"id":"c65907fb11d890c3","repo":"iflytek/astron-agent","slug":"artifact-upload-failed","errorCode":null,"errorMessage":"artifact_upload_failed","messagePattern":"artifact_upload_failed","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"core/agent/service/plugin/skill_sandbox.py","lineNumber":874,"sourceCode":"                    headers=headers,\n                    allow_redirects=False,\n                ) as response:\n                    if not 200 <= response.status < 300:\n                        raise ValueError\n                    response.raise_for_status()\n                    payload = await response.json(content_type=None)\n            code = payload.get(\"code\") if isinstance(payload, dict) else None\n            data = payload.get(\"data\") if isinstance(payload, dict) else None\n            if (\n                isinstance(code, bool)\n                or not isinstance(code, int)\n                or code != 0\n                or not isinstance(data, dict)\n            ):\n                raise ValueError\n            return data\n        except Exception:\n            raise RuntimeError(ARTIFACT_UPLOAD_FAILED_ERROR) from None\n","sourceCodeStart":856,"sourceCodeEnd":875,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/core/agent/service/plugin/skill_sandbox.py#L856-L875","documentation":"ArtifactUploader.upload POSTs a multipart form (flowId, uid, skillId, file, auth token header) to the artifact upload URL. Any failure — non-2xx status, redirect, invalid JSON, or a business envelope where code != 0 or data is not a dict — is re-raised as RuntimeError(ARTIFACT_UPLOAD_FAILED_ERROR) ('artifact_upload_failed').","triggerScenarios":"Upload endpoint returns 4xx/5xx or a redirect (allow_redirects=False), response body is not valid JSON, business code is non-zero, data field missing, upload token missing/invalid, or a network timeout (60s total).","commonSituations":"Artifact upload service down or returning 502 behind a gateway; expired/rotated X-Skill-Sandbox-Artifact-Token; upload URL env var pointing at the wrong environment; artifact exceeding a server-side size limit; workflow_id/uid misconfigured so the backend rejects the flow.","solutions":["Check the artifact upload service health and that artifact_upload_url points to the correct environment","Verify the upload token (X-Skill-Sandbox-Artifact-Token) is present and not expired, and that workflow_id/uid in SkillSandboxConfig are set correctly","Inspect the artifact size against server limits and compress or shrink it if rejected","Retry the upload after a transient failure; capture the upstream status/body in server logs to pinpoint 4xx vs 5xx causes"],"exampleFix":"// before: token loaded but possibly empty\nheaders = {'X-Skill-Sandbox-Artifact-Token': artifact_upload_token}\n// after\nif not artifact_upload_token:\n    raise RuntimeError('artifact upload token is not configured')\nheaders = {'X-Skill-Sandbox-Artifact-Token': artifact_upload_token}","handlingStrategy":"retry","validationCode":"from uploader import ArtifactUploader\nif not uploader.is_configured():\n    raise RuntimeError('artifact upload URL/token or workflow_id/uid not configured')\nif len(file_bytes) > MAX_UPLOAD_BYTES:\n    raise ValueError('artifact exceeds upload size limit')","typeGuard":"def upload_envelope_ok(payload) -> bool:\n    return (isinstance(payload, dict) and isinstance(payload.get('code'), int)\n            and not isinstance(payload.get('code'), bool)\n            and payload.get('code') == 0 and isinstance(payload.get('data'), dict))","tryCatchPattern":"for attempt in range(3):\n    try:\n        return await uploader.upload(name, data, ctype)\n    except RuntimeError:\n        if attempt == 2:\n            logger.error('artifact upload failed after retries')\n            raise\n        await asyncio.sleep(2 ** attempt)","preventionTips":["Monitor artifact upload service health and 5xx rates","Rotate and distribute the upload token before expiry","Verify artifact_upload_url per environment in deployment config","Log upstream status/body on failure to distinguish auth vs size vs availability"],"tags":["upload","http","artifact","auth","network"],"backgroundTag":"http-error-response","analyzedSha":"5e758547a83371a5a4b29dadf4ac03e8dd527635","analyzedAt":"2026-09-12T08:03:51.356Z","contentChangedAt":"2026-09-12T08:03:51.356Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}