{"record":{"id":"8c66e8548f784398","repo":"iflytek/astron-agent","slug":"workflow-protocol-empty","errorCode":"WORKFLOW_PROTOCOL_EMPTY","errorMessage":"ResponseEnum.WORKFLOW_PROTOCOL_EMPTY","messagePattern":"ResponseEnum\\.WORKFLOW_PROTOCOL_EMPTY","errorType":"error_code","errorClass":"BusinessException","httpStatus":null,"severity":"error","filePath":"console/backend/toolkit/src/main/java/com/iflytek/astron/console/toolkit/service/workflow/WorkflowService.java","lineNumber":4287,"sourceCode":"    }\n\n    private void assertSpacePublishManager(Long spaceId) {\n        if (spaceId == null) {\n            return;\n        }\n        SpaceRoleEnum role = spaceUserService.getRole(spaceId, UserInfoManagerHandler.getUserId());\n        if (SpaceRoleEnum.OWNER != role && SpaceRoleEnum.ADMIN != role) {\n            throw new BusinessException(ResponseEnum.INSUFFICIENT_PERMISSIONS);\n        }\n    }\n\n    public boolean isSimpleIo(Long id) {\n        Workflow workflow = getById(id);\n        dataPermissionCheckTool.checkWorkflowBelong(workflow, SpaceInfoUtil.getSpaceId());\n\n        String data = workflow.getData();\n        if (data == null) {\n            throw new BusinessException(ResponseEnum.WORKFLOW_PROTOCOL_EMPTY);\n        }\n\n        // Get start and end nodes\n        BizWorkflowData bizWorkflowData = JSON.parseObject(data, BizWorkflowData.class);\n        List<BizWorkflowNode> nodes = bizWorkflowData.getNodes();\n        BizWorkflowNode start = nodes.get(0);\n        BizWorkflowNode end = nodes.get(1);\n        if (!start.getId().startsWith(WorkflowConst.NodeType.START)) {\n            for (BizWorkflowNode node : nodes) {\n                if (node.getId().startsWith(WorkflowConst.NodeType.START)) {\n                    start = node;\n                    break;\n                }\n            }\n        }\n        if (!end.getId().startsWith(WorkflowConst.NodeType.END)) {\n            for (BizWorkflowNode node : nodes) {\n                if (node.getId().startsWith(WorkflowConst.NodeType.END)) {","sourceCodeStart":4269,"sourceCodeEnd":4305,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/console/backend/toolkit/src/main/java/com/iflytek/astron/console/toolkit/service/workflow/WorkflowService.java#L4269-L4305","documentation":"WORKFLOW_PROTOCOL_EMPTY indicates the workflow's serialized protocol payload (the `data` column) is null or blank when the service needs to parse it into BizWorkflowData. The platform treats a workflow without graph data as unusable, so isSimpleIo refuses to proceed rather than risk a NullPointerException on JSON.parseObject. It is thrown before any node inspection happens.","triggerScenarios":"Calling isSimpleIo(id) for a workflow whose `data` field is null — e.g. a just-created workflow row that has not been saved with graph content yet, a row whose protocol was wiped by a failed save/import, or an id pointing at a stub/migration placeholder record that passes the belong-check.","commonSituations":"Fetching a workflow created through an API path that inserts the row before the canvas first save; data migrated from an older schema where `data` was nullable; a test fixture with only id/flowId set; DB truncation or partial import leaving an empty protocol.","solutions":["Confirm the workflow actually has graph content: query the workflow table and check `data` is non-null/non-empty for that id","If the workflow is legitimately empty, open it in the editor and save at least a start/end node so the protocol is persisted","Fix the creation/import path so it writes `data` atomically with the row instead of inserting a null-protocol record first","Catch BusinessException with code WORKFLOW_PROTOCOL_EMPTY in the controller and return 400 telling the user the workflow graph is missing"],"exampleFix":"// before\nWorkflow wf = workflowService.getById(id);\nboolean simple = workflowService.isSimpleIo(wf.getId()); // throws if data==null\n// after\nWorkflow wf = workflowService.getById(id);\nif (wf == null || StringUtils.isBlank(wf.getData())) {\n    throw new BusinessException(ResponseEnum.WORKFLOW_PROTOCOL_EMPTY);\n}\nboolean simple = workflowService.isSimpleIo(wf.getId());","handlingStrategy":"validation","validationCode":"Workflow wf = workflowService.getById(id);\nif (wf == null) throw new BusinessException(ResponseEnum.WORKFLOW_NOT_EXIST);\nif (StringUtils.isBlank(wf.getData())) throw new BusinessException(ResponseEnum.WORKFLOW_PROTOCOL_EMPTY);","typeGuard":"boolean hasProtocol(Workflow wf) { return wf != null && StringUtils.isNotBlank(wf.getData()); }","tryCatchPattern":"try { service.isSimpleIo(id); } catch (BusinessException e) { if (\"WORKFLOW_PROTOCOL_EMPTY\".equals(e.getCode().toString())) { /* treat as empty graph: return 400 */ } else throw e; }","preventionTips":["Always save at least a start/end node when creating a workflow before calling read APIs","Insert workflow rows and their graph data in one transaction","Add a DB check/constraint or startup audit for workflows with null data"],"tags":["workflow","empty-protocol","data-integrity"],"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"}