iflytek/astron-agent · warning · BusinessException

8131

8131

Error message

workflow.artifact.file.type.not.allowed

What it means

WorkflowArtifactFileValidator.validate rejects artifact uploads whose filename extension is missing, is not in the configured allowed-extension list (SkillSandboxArtifactProperties.artifactAllowedExtensions), or has no registered media-type mapping in MEDIA_TYPES_BY_EXTENSION. The platform only accepts artifacts with a known, permitted extension (txt, md, csv, json, pdf, images, Office documents, zip). This is a policy error, not corruption: the file itself was never inspected.

Solutions

  1. Check the uploaded file's extension and rename/save it with a supported extension (txt, md, csv, json, pdf, png, jpg, jpeg, gif, webp, doc, xls, ppt, docx, xlsx, pptx, zip).
  2. Verify the workflow artifact allowed-extensions configuration (SkillSandboxArtifactProperties.artifactAllowedExtensions) includes the extension you need; add it if missing.
  3. If adding a genuinely new type, also add an entry to MEDIA_TYPES_BY_EXTENSION in WorkflowArtifactFileValidator — config alone is insufficient.

Example fix

// before (config omits the type)
artifact.allowed-extensions=txt,md,csv,json,pdf
// after
artifact.allowed-extensions=txt,md,csv,json,pdf,png,docx
Defensive patterns

Strategy: validation

Validate before calling

String ext = StringUtils.lowerCase(FilenameUtils.getExtension(file.getOriginalFilename()));
Set<String> allowed = properties.getArtifactAllowedExtensions();
boolean ok = StringUtils.isNotBlank(ext) && allowed.stream().anyMatch(ext::equalsIgnoreCase);
if (!ok) { /* reject before calling validate() */ }

Try / catch

try { validator.validate(file); } catch (BusinessException e) { if (e.getResponse() == ResponseEnum.WORKFLOW_ARTIFACT_FILE_TYPE_NOT_ALLOWED) { /* return 4xx with allowed-extension hint to the client */ } throw e; }

Prevention

When it happens

Trigger: Calling validate() with a MultipartFile whose originalFilename has no extension (e.g. 'README'), whose extension is not present in properties.getArtifactAllowedExtensions(), or whose extension is allowed in config but absent from the validator's MEDIA_TYPES_BY_EXTENSION map (e.g. an extension added to config but unsupported in code).

Common situations: Users uploading files like .exe, .sh, .docm, or extensionless files; admins narrowing artifactAllowedExtensions so previously accepted types are now rejected; a new extension added to config without code support; clients sending filenames without extensions after path normalization strips them.

Related errors


AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12). Data as JSON: /api/errors/a73c0b5110cd553a. Report an issue: GitHub.

Appendix: source

Thrown at console/backend/toolkit/src/main/java/com/iflytek/astron/console/toolkit/service/workflow/WorkflowArtifactFileValidator.java:143

        this.properties = Objects.requireNonNull(properties);
        this.ooxmlResourceLimits = Objects.requireNonNull(ooxmlResourceLimits);
    }

    public ValidatedArtifact validate(MultipartFile file) {
        if (file == null || file.isEmpty() || StringUtils.isBlank(file.getOriginalFilename())) {
            throw new BusinessException(ResponseEnum.PARAM_ERROR);
        }
        if (file.getSize() <= 0 || file.getSize() > properties.getArtifactMaxFileSize().toBytes()) {
            throw new BusinessException(ResponseEnum.WORKFLOW_ARTIFACT_FILE_TOO_LARGE);
        }

        String fileName = normalizeFileName(file.getOriginalFilename());
        String extension = StringUtils.lowerCase(FilenameUtils.getExtension(fileName), Locale.ROOT);
        Set<String> configuredExtensions = properties.getArtifactAllowedExtensions();
        if (StringUtils.isBlank(extension)
                || configuredExtensions.stream().noneMatch(extension::equalsIgnoreCase)
                || !MEDIA_TYPES_BY_EXTENSION.containsKey(extension)) {
            throw new BusinessException(ResponseEnum.WORKFLOW_ARTIFACT_FILE_TYPE_NOT_ALLOWED);
        }

        String declaredType = normalizeMediaType(file.getContentType());
        if (ACTIVE_CONTENT_TYPES.contains(declaredType)
                || (!StringUtils.isBlank(declaredType)
                        && !OCTET_STREAM.equals(declaredType)
                        && !MEDIA_TYPES_BY_EXTENSION.get(extension).contains(declaredType))) {
            throw new BusinessException(ResponseEnum.WORKFLOW_ARTIFACT_CONTENT_TYPE_MISMATCH);
        }

        // Preflight Office containers before the general detector. OOXML resource limits run
        // before its POI package parse inside validateOoxmlContainer.
        validateOfficeContainer(file, extension);
        String detectedType;
        try (InputStream input = file.getInputStream()) {
            detectedType = normalizeMediaType(tika.detect(input, fileName));
        } catch (IOException exception) {
            throw new BusinessException(ResponseEnum.WORKFLOW_ARTIFACT_CONTENT_TYPE_MISMATCH);

View on GitHub (pinned to 5e758547a8)