{"record":{"id":"610639daba1476aa","repo":"iflytek/astron-agent","slug":"workflow-artifact-quota-exceeded","errorCode":"WORKFLOW_ARTIFACT_QUOTA_EXCEEDED","errorMessage":"WORKFLOW_ARTIFACT_QUOTA_EXCEEDED","messagePattern":"WORKFLOW_ARTIFACT_QUOTA_EXCEEDED","errorType":"error_code","errorClass":"BusinessException","httpStatus":null,"severity":"error","filePath":"console/backend/toolkit/src/main/java/com/iflytek/astron/console/toolkit/service/workflow/WorkflowArtifactService.java","lineNumber":457,"sourceCode":"    }\n\n    private void enforceWorkflowArtifactQuota(Long workflowId, long incomingFileBytes) {\n        long activeFileCount = baseMapper.countActiveByWorkflowId(workflowId);\n        long activeTotalBytes = baseMapper.sumActiveBytesByWorkflowId(workflowId);\n        long maxFileCount = artifactProperties.getArtifactMaxActiveFilesPerWorkflow();\n        long maxTotalBytes =\n                artifactProperties.getArtifactMaxActiveTotalSizePerWorkflow().toBytes();\n        boolean fileCountExceeded = activeFileCount >= maxFileCount;\n        boolean totalBytesExceeded = incomingFileBytes > maxTotalBytes\n                || activeTotalBytes > maxTotalBytes - incomingFileBytes;\n        if (fileCountExceeded || totalBytesExceeded) {\n            log.warn(\n                    \"Rejected workflow artifact because its active quota would be exceeded, workflowId={}, activeFiles={}, activeBytes={}, incomingBytes={}\",\n                    workflowId,\n                    activeFileCount,\n                    activeTotalBytes,\n                    incomingFileBytes);\n            throw new BusinessException(ResponseEnum.WORKFLOW_ARTIFACT_QUOTA_EXCEEDED);\n        }\n    }\n\n    /** Marks every artifact for a deleted workflow so the scheduled object purge can drain it. */\n    @Transactional\n    public int tombstoneWorkflowArtifacts(Long workflowId) {\n        if (workflowId == null) {\n            throw new BusinessException(ResponseEnum.PARAM_ERROR);\n        }\n        return baseMapper.update(\n                null,\n                Wrappers.lambdaUpdate(WorkflowArtifact.class)\n                        .eq(WorkflowArtifact::getWorkflowId, workflowId)\n                        .eq(WorkflowArtifact::getDeleted, Boolean.FALSE)\n                        .set(WorkflowArtifact::getDeleted, Boolean.TRUE)\n                        .set(WorkflowArtifact::getUpdateTime, LocalDateTime.now()));\n    }\n","sourceCodeStart":439,"sourceCodeEnd":475,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/console/backend/toolkit/src/main/java/com/iflytek/astron/console/toolkit/service/workflow/WorkflowArtifactService.java#L439-L475","documentation":"Thrown by enforceWorkflowArtifactQuota when uploading a new artifact would push the workflow over its configured active-artifact quota, measured in file count or total active bytes. The service logs activeFiles/activeBytes/incomingBytes and rejects before writing the object.","triggerScenarios":"uploadInternal called when activeFileCount+1 exceeds the file-count quota, or activeTotalBytes+incomingFileBytes exceeds the byte quota for the workflow.","commonSituations":"Many attachments accumulated on a long-lived workflow; uploading a large file to a nearly-full workflow; quota lowered after artifacts already stored; retry loops re-uploading the same artifacts.","solutions":["Delete unneeded artifacts to free quota, then retry the upload","Upload a smaller file or compress/split the payload","Raise the workflow artifact quota configuration","Check for duplicate/retry uploads inflating active counts"],"exampleFix":"// before\nlong incoming = file.getSize(); // exceeds remaining quota\nuploadInternal(wfId, flowId, uid, spaceId, file);\n// after\nif (file.getSize() + activeTotalBytes(wfId) <= quotaBytes(wfId)) {\n    uploadInternal(wfId, flowId, uid, spaceId, file);\n} else {\n    throw new BusinessException(ResponseEnum.WORKFLOW_ARTIFACT_QUOTA_EXCEEDED);\n}","handlingStrategy":"try-catch","validationCode":"boolean fitsQuota(Long wfId, long bytes) {\n    return activeTotalBytes(wfId) + bytes <= quotaBytes(wfId)\n        && activeFileCount(wfId) + 1 <= quotaFiles(wfId);\n}","typeGuard":null,"tryCatchPattern":"try { uploadInternal(wfId, flowId, uid, spaceId, file); } catch (BusinessException e) {\n    if (e.getCode() == ResponseEnum.WORKFLOW_ARTIFACT_QUOTA_EXCEEDED) {\n        promptUserToFreeQuota();\n    } else throw e;\n}","preventionTips":["Check current usage against quota in the UI before upload","Clean up unused artifacts regularly","Avoid retry loops that re-upload identical artifacts","Keep quotas and usage in a single query to avoid drift"],"tags":["quota","upload","limit-exceeded"],"backgroundTag":"file-size-limit-exceeded","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"}