iflytek/astron-agent · error · BusinessException
8103
8103
Error message
workflow.version.publish.failed
What it means
Thrown by updateChannelResultAfterAuthorization when the publish-result UPDATE matches a row count other than 1, or when any exception occurs inside the update block (the catch clause rethrows the same error). It signals the platform could not persist the normalized publish result onto the workflow version.
Solutions
- Check the server logs for the line 'Workflow version publish result failed, failure reason: ...' — the logged exception reveals the true root cause (NPE vs SQL error vs 0-row update).
- Verify the version is still live: SELECT id, flow_id, deleted FROM workflow_version WHERE id = <id> AND deleted = 0.
- If deleted concurrently, treat the update as skippable — do not retry against a deleted version.
- Ensure createDto.id and publishResult are set and publishResult is a value accepted by WorkflowConst.PublishResult.normalize.
- For DB errors, check connectivity/lock contention and retry with backoff; fix the catch block to preserve the original cause if it masks real errors.
Example fix
// before
} catch (Exception e) {
log.info("failed: {}", e);
throw new BusinessException(ResponseEnum.WORKFLOW_VERSION_PUBLISH_FAILED);
}
// after
} catch (BusinessException be) {
throw be; // preserve specific errors
} catch (Exception e) {
log.error("Publish result update failed for version {}", createDto.getId(), e); // log stack trace
throw new BusinessException(ResponseEnum.WORKFLOW_VERSION_PUBLISH_FAILED);
} Defensive patterns
Strategy: retry
Validate before calling
// Pre-check the target row is live and uniquely matchable
int live = versionMapper.selectCount(Wrappers.lambdaQuery(WorkflowVersion.class)
.eq(WorkflowVersion::getId, dto.getId())
.eq(WorkflowVersion::getFlowId, resolvedFlowId)
.eq(WorkflowVersion::getDeleted, false));
if (live != 1) { /* abort: row missing or duplicated */ } Type guard
boolean isPublishableResult(WorkflowVersion dto) {
return dto != null && dto.getId() != null
&& WorkflowConst.PublishResult.normalize(dto.getPublishResult()) != null;
} Try / catch
int attempts = 0;
while (attempts < 3) {
try {
versionService.updateChannelResult(dto);
break;
} catch (BusinessException e) {
if (++attempts >= 3 || "workflow.version.not.found".equals(e.getMessage())) throw e;
Thread.sleep(200L * attempts); // transient DB issue: retry with backoff
}
} Prevention
- Read the logged failure reason in server logs — the catch-all hides the real cause (NPE, SQL error, 0-row update).
- Ensure publishResult values are within those accepted by WorkflowConst.PublishResult.normalize.
- Retry only transient DB failures; never retry when the version was concurrently deleted.
- Use short transactions and appropriate isolation to reduce deadlocks/lock-timeout on the version row.
- Alert on update row counts != 1 to catch duplicate-id data anomalies early.
When it happens
Trigger: The version was deleted between the authorization check and the UPDATE (deleted=2); the flowId on the DTO no longer matches the row; createDto.getId() is null (NPE in the wrapper caught and rethrown); a DB error (connection, lock timeout, constraint) occurs and is swallowed into this generic failure.
Common situations: Race between a delete and a publish-result callback; duplicate ids causing update to affect 2 rows; DB connection pool exhaustion or deadlock; invalid publishResult value causing a column length/constraint failure; underlying exception's real cause hidden by the catch-all rethrow.
Related errors
- SaveSnapshotDidNotStabilizeError
- 67011
- INTERNAL_SERVER_ERROR
- WORKFLOW_IMPORT_FAILED
- RAGFlow chunk snapshot remained incomplete after retries…
AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12).
Data as JSON: /api/errors/82ff969430556742.
Report an issue: GitHub.
Appendix: source
Thrown at console/backend/toolkit/src/main/java/com/iflytek/astron/console/toolkit/service/workflow/VersionService.java:725
throw new BusinessException(ResponseEnum.WORKFLOW_NOT_EXIST);
}
return workflow;
}
private ApiResult<JSONObject> updateChannelResultAfterAuthorization(
WorkflowVersion createDto) {
try {
LambdaUpdateWrapper<WorkflowVersion> updateWrapper = new LambdaUpdateWrapper<>();
// Update flowId corresponding records, set isVersion to 2
updateWrapper.eq(WorkflowVersion::getId, createDto.getId())
.eq(WorkflowVersion::getFlowId, createDto.getFlowId())
.eq(WorkflowVersion::getDeleted, false)
.set(WorkflowVersion::getPublishResult,
WorkflowConst.PublishResult.normalize(createDto.getPublishResult()))
.set(WorkflowVersion::getUpdatedTime, new Date());
// Execute update
if (workflowVersionMapper.update(null, updateWrapper) != 1) {
throw new BusinessException(ResponseEnum.WORKFLOW_VERSION_PUBLISH_FAILED);
}
log.info("Workflow version publish result successful, version ID: {}, publish result: {}", createDto.getId(), createDto.getPublishResult());
return ApiResult.success(new JSONObject());
} catch (Exception e) {
log.info("Workflow version publish result failed, failure reason: {}, version ID: {}, publish result: {}", e, createDto.getId(), createDto.getPublishResult());
throw new BusinessException(ResponseEnum.WORKFLOW_VERSION_PUBLISH_FAILED);
}
}
/**
* Get maximum version for a specific bot.
*
* @param botId Bot ID to query maximum version for
* @return API result with maximum version info
*/
public ApiResult<JSONObject> getMaxVersion(String botId) {
log.info("Querying workflow maximum version number, botId: {}", botId);View on GitHub (pinned to 5e758547a8)