{"record":{"id":"576059d93c0dbfca","repo":"iflytek/astron-agent","slug":"workflow-skill-name-desc-empty","errorCode":"WORKFLOW_SKILL_NAME_DESC_EMPTY","errorMessage":"WORKFLOW_SKILL_NAME_DESC_EMPTY","messagePattern":"WORKFLOW_SKILL_NAME_DESC_EMPTY","errorType":"error_code","errorClass":"BusinessException","httpStatus":null,"severity":"warning","filePath":"console/backend/hub/src/main/java/com/iflytek/astron/console/hub/service/workflow/impl/WorkflowSkillExportServiceImpl.java","lineNumber":67,"sourceCode":"    private final DataPermissionCheckTool dataPermissionCheckTool;\n\n    @Override\n    public WorkflowSkillExportResponse exportSkill(WorkflowSkillExportRequest request) {\n        if (request == null || request.getBotId() == null || request.getWorkflowId() == null) {\n            throw new BusinessException(ResponseEnum.PARAMETER_ERROR);\n        }\n\n        Workflow workflow = workflowService.getById(request.getWorkflowId());\n        if (workflow == null) {\n            throw new BusinessException(ResponseEnum.BOT_NOT_EXIST);\n        }\n        dataPermissionCheckTool.checkWorkflowBelong(workflow, SpaceInfoUtil.getSpaceId());\n\n        String workflowName = StringUtils.defaultIfBlank(request.getWorkflowName(), workflow.getName());\n        String workflowDescription =\n                StringUtils.defaultIfBlank(request.getWorkflowDescription(), workflow.getDescription());\n        if (StringUtils.isBlank(workflowName) || StringUtils.isBlank(workflowDescription)) {\n            throw new BusinessException(ResponseEnum.WORKFLOW_SKILL_NAME_DESC_EMPTY);\n        }\n\n        BotApiInfoDTO apiInfo = publishApiService.getApiInfo(request.getBotId());\n        if (!hasPublishedApi(apiInfo)) {\n            throw new BusinessException(ResponseEnum.WORKFLOW_SKILL_API_NOT_READY);\n        }\n\n        List<BizInputOutput> inputs = extractWorkflowInputs(workflow);\n        SkillMetadata metadata = generateSkillMetadata(workflowName, workflowDescription, workflow.getId());\n        String content = buildSkillContent(metadata, workflowName, workflowDescription, apiInfo, inputs);\n        return new WorkflowSkillExportResponse(SKILL_FILE_NAME, content, metadata.aiGenerated());\n    }\n\n    private boolean hasPublishedApi(BotApiInfoDTO apiInfo) {\n        return apiInfo != null\n                && StringUtils.isNotBlank(apiInfo.getAppId())\n                && StringUtils.isNotBlank(apiInfo.getAppKey())\n                && StringUtils.isNotBlank(apiInfo.getAppSecret())","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/console/backend/hub/src/main/java/com/iflytek/astron/console/hub/service/workflow/impl/WorkflowSkillExportServiceImpl.java#L49-L85","documentation":"exportSkill resolves the workflow name/description from the request or falls back to the stored workflow, and throws WORKFLOW_SKILL_NAME_DESC_EMPTY when either resolved value is blank. A skill export requires a non-empty name and description because both are embedded into the generated skill metadata and content.","triggerScenarios":"Both request.workflowName and workflow.name are blank, or both request.workflowDescription and workflow.description are blank — e.g. exporting a workflow that was created without a description and the caller didn't supply one.","commonSituations":"User skips the description field in the workflow editor then tries to export; a client sends empty-string name/description which defeats the fallback (defaultIfBlank falls through to an empty workflow field); imported workflows with missing metadata.","solutions":["Pass workflowName and workflowDescription explicitly in the WorkflowSkillExportRequest.","Open the workflow in the editor and set a name and description, then retry the export.","If empty strings are being sent, send null/omit the fields so the server falls back to the stored workflow values.","Add a required description field in the workflow-creation flow to prevent nameless/undescribed workflows."],"exampleFix":"// before\nexportSkill({botId: 123, workflowId: 456}); // workflow has blank description\n// after\nexportSkill({botId: 123, workflowId: 456, workflowName: \"My Skill\", workflowDescription: \"Exports orders via API\"});","handlingStrategy":"validation","validationCode":"String name = StringUtils.defaultIfBlank(req.getWorkflowName(), workflow.getName());\nString desc = StringUtils.defaultIfBlank(req.getWorkflowDescription(), workflow.getDescription());\nif (StringUtils.isBlank(name) || StringUtils.isBlank(desc)) {\n    promptUserForNameAndDescription(); // before calling export\n}","typeGuard":"boolean hasSkillNameAndDescription(String name, String desc) {\n    return StringUtils.isNotBlank(name) && StringUtils.isNotBlank(desc);\n}","tryCatchPattern":"try {\n    return exportSkill(request);\n} catch (BusinessException e) {\n    if (\"WORKFLOW_SKILL_NAME_DESC_EMPTY\".equals(e.getCode())) {\n        return badRequest(\"workflow name and description are required for skill export\");\n    }\n    throw e;\n}","preventionTips":["Require a description when creating workflows","Send explicit workflowName/workflowDescription rather than empty strings","Trim and validate metadata client-side before export"],"tags":["validation","metadata","workflow-export","java"],"backgroundTag":"empty-required-field","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"}