{"record":{"id":"82ff969430556742","repo":"iflytek/astron-agent","slug":"8103-workflow-version-publish-failed","errorCode":"8103","errorMessage":"workflow.version.publish.failed","messagePattern":"workflow\\.version\\.publish\\.failed","errorType":"error_code","errorClass":"BusinessException","httpStatus":null,"severity":"error","filePath":"console/backend/toolkit/src/main/java/com/iflytek/astron/console/toolkit/service/workflow/VersionService.java","lineNumber":725,"sourceCode":"            throw new BusinessException(ResponseEnum.WORKFLOW_NOT_EXIST);\n        }\n        return workflow;\n    }\n\n    private ApiResult<JSONObject> updateChannelResultAfterAuthorization(\n            WorkflowVersion createDto) {\n        try {\n            LambdaUpdateWrapper<WorkflowVersion> updateWrapper = new LambdaUpdateWrapper<>();\n            // Update flowId corresponding records, set isVersion to 2\n            updateWrapper.eq(WorkflowVersion::getId, createDto.getId())\n                    .eq(WorkflowVersion::getFlowId, createDto.getFlowId())\n                    .eq(WorkflowVersion::getDeleted, false)\n                    .set(WorkflowVersion::getPublishResult,\n                            WorkflowConst.PublishResult.normalize(createDto.getPublishResult()))\n                    .set(WorkflowVersion::getUpdatedTime, new Date());\n            // Execute update\n            if (workflowVersionMapper.update(null, updateWrapper) != 1) {\n                throw new BusinessException(ResponseEnum.WORKFLOW_VERSION_PUBLISH_FAILED);\n            }\n            log.info(\"Workflow version publish result successful, version ID: {}, publish result: {}\", createDto.getId(), createDto.getPublishResult());\n\n            return ApiResult.success(new JSONObject());\n        } catch (Exception e) {\n            log.info(\"Workflow version publish result failed, failure reason: {}, version ID: {}, publish result: {}\", e, createDto.getId(), createDto.getPublishResult());\n            throw new BusinessException(ResponseEnum.WORKFLOW_VERSION_PUBLISH_FAILED);\n        }\n    }\n\n    /**\n     * Get maximum version for a specific bot.\n     *\n     * @param botId Bot ID to query maximum version for\n     * @return API result with maximum version info\n     */\n    public ApiResult<JSONObject> getMaxVersion(String botId) {\n        log.info(\"Querying workflow maximum version number, botId: {}\", botId);","sourceCodeStart":707,"sourceCodeEnd":743,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/console/backend/toolkit/src/main/java/com/iflytek/astron/console/toolkit/service/workflow/VersionService.java#L707-L743","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\n} catch (Exception e) {\n    log.info(\"failed: {}\", e);\n    throw new BusinessException(ResponseEnum.WORKFLOW_VERSION_PUBLISH_FAILED);\n}\n// after\n} catch (BusinessException be) {\n    throw be; // preserve specific errors\n} catch (Exception e) {\n    log.error(\"Publish result update failed for version {}\", createDto.getId(), e); // log stack trace\n    throw new BusinessException(ResponseEnum.WORKFLOW_VERSION_PUBLISH_FAILED);\n}","handlingStrategy":"retry","validationCode":"// Pre-check the target row is live and uniquely matchable\nint live = versionMapper.selectCount(Wrappers.lambdaQuery(WorkflowVersion.class)\n        .eq(WorkflowVersion::getId, dto.getId())\n        .eq(WorkflowVersion::getFlowId, resolvedFlowId)\n        .eq(WorkflowVersion::getDeleted, false));\nif (live != 1) { /* abort: row missing or duplicated */ }","typeGuard":"boolean isPublishableResult(WorkflowVersion dto) {\n    return dto != null && dto.getId() != null\n        && WorkflowConst.PublishResult.normalize(dto.getPublishResult()) != null;\n}","tryCatchPattern":"int attempts = 0;\nwhile (attempts < 3) {\n    try {\n        versionService.updateChannelResult(dto);\n        break;\n    } catch (BusinessException e) {\n        if (++attempts >= 3 || \"workflow.version.not.found\".equals(e.getMessage())) throw e;\n        Thread.sleep(200L * attempts); // transient DB issue: retry with backoff\n    }\n}","preventionTips":["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."],"tags":["mybatis-plus","database-write","publish-result","race-condition"],"backgroundTag":"database-write-failed","analyzedSha":"5e758547a83371a5a4b29dadf4ac03e8dd527635","analyzedAt":"2026-09-12T08:03:51.356Z","contentChangedAt":"2026-09-12T08:03:51.356Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}