iflytek/astron-agent · error · BusinessException
WORKFLOW_SKILL_API_NOT_READY
WORKFLOW_SKILL_API_NOT_READY
Error message
WORKFLOW_SKILL_API_NOT_READY
What it means
exportSkill requires the target bot to have a published API. It fetches BotApiInfoDTO via publishApiService.getApiInfo(botId) and throws WORKFLOW_SKILL_API_NOT_READY when hasPublishedApi(apiInfo) is false — i.e. no published API endpoint exists for the bot, so a callable skill cannot be generated.
Solutions
- Publish the bot (e.g. via the market/channel publish flow) and wait until it is on-shelf with an active API, then retry exportSkill.
- Check the bot's publish status via the publish-status API before exporting.
- Confirm the botId passed is the one that was actually published, not an old or sibling bot.
- If publish is stuck in review, contact an admin or check the moderation record for the bot.
Example fix
// before
exportSkill({botId: draftBotId, workflowId: 456}); // bot never published
// after
await publishApi.publishBot({botId: draftBotId, channel: "market"});
await waitForPublishComplete(draftBotId);
exportSkill({botId: draftBotId, workflowId: 456}); Defensive patterns
Strategy: validation
Validate before calling
BotApiInfoDTO apiInfo = publishApiService.getApiInfo(botId);
if (apiInfo == null || apiInfo.getApiUrl() == null) {
throw new IllegalStateException("bot " + botId + " has no published API; publish it first");
} Type guard
boolean hasPublishedApi(BotApiInfoDTO apiInfo) {
return apiInfo != null && StringUtils.isNotBlank(apiInfo.getApiUrl());
} Try / catch
try {
return exportSkill(request);
} catch (BusinessException e) {
if ("WORKFLOW_SKILL_API_NOT_READY".equals(e.getCode())) {
guideUserToPublishBot(request.getBotId());
}
throw e;
} Prevention
- Publish the bot and confirm on-shelf status before exporting a skill
- Gate the export button on the bot's published-API status from the publish-status API
- Verify the botId is the one actually published, not a draft duplicate
When it happens
Trigger: Calling exportSkill for a botId whose bot has never been published, whose publish is still in review/pending, or whose publish channels were all removed so getApiInfo returns null/empty API info.
Common situations: User tries to export a skill from a draft-only bot; the bot publish is pending moderation; the bot was taken offline (off-shelf) before export; botId points to a different bot than the one actually published.
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/3c8ef411398d63e7.
Report an issue: GitHub.
Appendix: source
Thrown at console/backend/hub/src/main/java/com/iflytek/astron/console/hub/service/workflow/impl/WorkflowSkillExportServiceImpl.java:72
throw new BusinessException(ResponseEnum.PARAMETER_ERROR);
}
Workflow workflow = workflowService.getById(request.getWorkflowId());
if (workflow == null) {
throw new BusinessException(ResponseEnum.BOT_NOT_EXIST);
}
dataPermissionCheckTool.checkWorkflowBelong(workflow, SpaceInfoUtil.getSpaceId());
String workflowName = StringUtils.defaultIfBlank(request.getWorkflowName(), workflow.getName());
String workflowDescription =
StringUtils.defaultIfBlank(request.getWorkflowDescription(), workflow.getDescription());
if (StringUtils.isBlank(workflowName) || StringUtils.isBlank(workflowDescription)) {
throw new BusinessException(ResponseEnum.WORKFLOW_SKILL_NAME_DESC_EMPTY);
}
BotApiInfoDTO apiInfo = publishApiService.getApiInfo(request.getBotId());
if (!hasPublishedApi(apiInfo)) {
throw new BusinessException(ResponseEnum.WORKFLOW_SKILL_API_NOT_READY);
}
List<BizInputOutput> inputs = extractWorkflowInputs(workflow);
SkillMetadata metadata = generateSkillMetadata(workflowName, workflowDescription, workflow.getId());
String content = buildSkillContent(metadata, workflowName, workflowDescription, apiInfo, inputs);
return new WorkflowSkillExportResponse(SKILL_FILE_NAME, content, metadata.aiGenerated());
}
private boolean hasPublishedApi(BotApiInfoDTO apiInfo) {
return apiInfo != null
&& StringUtils.isNotBlank(apiInfo.getAppId())
&& StringUtils.isNotBlank(apiInfo.getAppKey())
&& StringUtils.isNotBlank(apiInfo.getAppSecret())
&& StringUtils.isNotBlank(apiInfo.getServiceUrl())
&& StringUtils.isNotBlank(apiInfo.getFlowId());
}
private List<BizInputOutput> extractWorkflowInputs(Workflow workflow) {View on GitHub (pinned to 5e758547a8)