apache/dolphinscheduler · error · ServiceException
file extension cannot not change
Error message
file extension cannot not change
What it means
UpdateFileDtoValidator.validate enforces that when updating a resource file, the replacement file uploaded via multipart has the same file extension as the existing resource at fileAbsolutePath. If Files.getFileExtension of the uploaded file's name differs from the extension of the target resource path, a ServiceException('file extension cannot not change') is thrown and the update is rejected. This prevents users from silently converting a resource's type (e.g. replacing a .py script with a .jar).
Source
Thrown at dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/validator/resource/UpdateFileDtoValidator.java:50
@Component
public class UpdateFileDtoValidator extends AbstractResourceValidator<UpdateFileDto> {
public UpdateFileDtoValidator(StorageOperator storageOperator, TenantDao tenantDao) {
super(storageOperator, tenantDao);
}
@Override
public void validate(UpdateFileDto updateFileDto) {
String fileAbsolutePath = updateFileDto.getFileAbsolutePath();
User loginUser = updateFileDto.getLoginUser();
MultipartFile file = updateFileDto.getFile();
if (!Objects.equals(
Files.getFileExtension(
file.getOriginalFilename() == null ? file.getName() : file.getOriginalFilename()),
Files.getFileExtension(updateFileDto.getFileAbsolutePath()))) {
throw new ServiceException("file extension cannot not change");
}
exceptionResourceAbsolutePathInvalidated(fileAbsolutePath);
exceptionResourceNotExists(fileAbsolutePath);
exceptionResourceIsNotFile(fileAbsolutePath);
exceptionUserNoResourcePermission(loginUser, fileAbsolutePath);
exceptionFileInvalidated(file);
}
}
View on GitHub (pinned to 02eac45a1b)
Solutions
- Re-upload a file whose name ends with the same extension as the existing resource path (match getFileExtension of fileAbsolutePath).
- Rename the uploaded file before the request: new File("same-name." + extensionOfTarget).
- If a type change is genuinely needed, delete the old resource and create a new one with the correct extension instead of updating.
- Ensure the HTTP client preserves the original filename in multipart Content-Disposition (set filename explicitly).
Example fix
// before: uploading replacement with mismatched name
file = new File("/tmp/script.txt"); // target resource is script.py
// after
File fixed = new File("/tmp/script.py"); // same extension as fileAbsolutePath
updateFileDto.setFile(fixed); Defensive patterns
Strategy: validation
Validate before calling
const targetExt = filePath.split('.').pop().toLowerCase();
const uploadExt = (file.name || '').split('.').pop().toLowerCase();
if (targetExt !== uploadExt) {
throw new Error(`Extension mismatch: target .${targetExt}, upload .${uploadExt}`);
} Try / catch
try {
await updateResource(dto);
} catch (e) {
if (e.message.includes('file extension cannot not change')) {
// surface: rename file to match resource extension and retry
}
throw e;
} Prevention
- Always derive the uploaded filename from the original resource name, not from a local temp file.
- Verify multipart clients preserve Content-Disposition filename.
- Delete-and-recreate resources when a type change is intentional.
- Check the file picker for auto-appended extensions like .download.
When it happens
Trigger: Calling the resource-update API (UpdateResourceController / updateResource) with an UpdateFileDto whose uploaded MultipartFile has an original filename whose extension differs from the extension of fileAbsolutePath, e.g. updating resources/script.py with a file named script.txt.
Common situations: Renaming or re-saving a file locally before upload so the extension changes (export.csv -> export.xlsx); uploading a temp file without its extension (browser stripping .py); picking the wrong file in the UI; drag-and-drop from tools that append extensions like .download or .crdownload.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- url can not be null
- 10001
- namespace %s does not exist in k8s cluster, please create na
- ID token is missing required claims
- REQUEST_PARAMS_NOT_VALID_ERROR
AI-assisted analysis of apache/dolphinscheduler@02eac45a1b (2026-09-06).
Data as JSON: /api/errors/255db065e19765fc.
Report an issue: GitHub.