iflytek/astron-agent · error · BusinessException
8102
8102
Error message
workflow.version.reduction.failed
What it means
restore throws WORKFLOW_VERSION_REDUCTION_FAILED (code 8102) when the bulk update that marks all versions of the flow as isVersion=2 (non-current) affects fewer than 1 row. Restore requires demarcating old versions before promoting the target one.
Solutions
- Check that at least one live version row exists for the flowId before restoring
- Retry the restore — a transient race may have resolved; re-fetch state first
- Serialize restore/delete operations per flowId (lock or optimistic check) to avoid concurrent mutation
- Inspect workflow_version rows (is_version, deleted) for the flow to confirm DB state before retrying
Example fix
// before
if (workflowVersionMapper.update(null, updateWrapper1) < 1) {
throw new BusinessException(ResponseEnum.WORKFLOW_VERSION_REDUCTION_FAILED);
}
// after
int updated = workflowVersionMapper.update(null, updateWrapper1);
if (updated < 1) {
log.warn("restore: no live versions to demote for flowId={}", createDto.getFlowId());
throw new BusinessException(ResponseEnum.WORKFLOW_VERSION_REDUCTION_FAILED);
} Defensive patterns
Strategy: retry
Validate before calling
Long liveVersions = workflowVersionMapper.selectCount(new LambdaQueryWrapper<WorkflowVersion>()
.eq(WorkflowVersion::getFlowId, flowId).eq(WorkflowVersion::getDeleted, false));
if (liveVersions == 0) { /* nothing to demote — restore precondition broken */ } Try / catch
try {
return svc.restore(dto);
} catch (BusinessException e) {
if (e.getCode() == 8102) { recheckFlowState(); return retryOnceOrReport(dto); }
throw e;
} Prevention
- Serialize restore and logicDelete per flowId (distributed lock or DB row lock)
- Run the whole restore in one transaction to avoid partial state
- Verify live versions exist before starting restore
- Avoid concurrent restore of the same flow from multiple sessions
When it happens
Trigger: workflowVersionMapper.update(null, updateWrapper1) returns 0 — no live versions exist for the flowId at that moment (e.g. all deleted concurrently) even though the target version was found moments earlier.
Common situations: Concurrent logicDelete removing all versions between the select and update; data race between two restore calls; flow whose versions were purged externally.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12).
Data as JSON: /api/errors/82f4663ee7664e8d.
Report an issue: GitHub.
Appendix: source
Thrown at console/backend/toolkit/src/main/java/com/iflytek/astron/console/toolkit/service/workflow/VersionService.java:535
.eq(WorkflowVersion::getId, createDto.getId())
.eq(WorkflowVersion::getFlowId, createDto.getFlowId())
.eq(WorkflowVersion::getDeleted, false)
.last("limit 1"));
if (workflowVersion == null) {
throw new BusinessException(ResponseEnum.WORKFLOW_VERSION_NOT_FOUND);
}
String data = workflowVersion.getData();
// Update workflow table protocol data
updateFlowIdWorkflow(createDto.getFlowId(), data);
LambdaUpdateWrapper<WorkflowVersion> updateWrapper1 = new LambdaUpdateWrapper<>();
// Update flowId corresponding records, set isVersion to 2
updateWrapper1.eq(WorkflowVersion::getFlowId, createDto.getFlowId())
.eq(WorkflowVersion::getDeleted, false)
.set(WorkflowVersion::getIsVersion, 2);
// Execute update
if (workflowVersionMapper.update(null, updateWrapper1) < 1) {
throw new BusinessException(ResponseEnum.WORKFLOW_VERSION_REDUCTION_FAILED);
}
LambdaUpdateWrapper<WorkflowVersion> updateWrapper2 = new LambdaUpdateWrapper<>();
// Update id corresponding records, set isVersion to 1
updateWrapper2
.eq(WorkflowVersion::getId, createDto.getId())
.eq(WorkflowVersion::getFlowId, createDto.getFlowId())
.eq(WorkflowVersion::getDeleted, false)
.set(WorkflowVersion::getIsVersion, 1);
// Execute update
if (workflowVersionMapper.update(null, updateWrapper2) != 1) {
throw new BusinessException(ResponseEnum.WORKFLOW_VERSION_REDUCTION_FAILED);
}
return ApiResult.success(new JSONObject());
} catch (BusinessException e) {
throw e;View on GitHub (pinned to 5e758547a8)