{"record":{"id":"90828c0d2650351e","repo":"flowable/flowable-engine","slug":"file-must-be-of-type-app","errorCode":null,"errorMessage":"File must be of type .app","messagePattern":"File must be of type \\.app","errorType":"validation","errorClass":"FlowableIllegalArgumentException","httpStatus":400,"severity":"error","filePath":"modules/flowable-app-engine-rest/src/main/java/org/flowable/app/rest/service/api/repository/AppDeploymentCollectionResource.java","lineNumber":190,"sourceCode":"            String fileName = file.getOriginalFilename();\n            if (StringUtils.isEmpty(fileName) || !(fileName.endsWith(\".app\") || fileName.toLowerCase().endsWith(\".bar\") || fileName.toLowerCase().endsWith(\".zip\"))) {\n                fileName = file.getName();\n            }\n\n            if (fileName.endsWith(\".app\")) {\n                try (final InputStream fileInputStream = file.getInputStream()) {\n                    deploymentBuilder.addInputStream(fileName, fileInputStream);\n                }\n\n            } else if (fileName.toLowerCase().endsWith(\".bar\") || fileName.toLowerCase().endsWith(\".zip\")) {\n                try (InputStream fileInputStream = file.getInputStream();\n                        ZipInputStream zipInputStream = new ZipInputStream(fileInputStream)) {\n                    \n                    deploymentBuilder.addZipInputStream(zipInputStream);\n                }\n\n            } else {\n                throw new FlowableIllegalArgumentException(\"File must be of type .app\");\n            }\n            \n            if (!decodedQueryStrings.containsKey(\"deploymentName\") || StringUtils.isEmpty(decodedQueryStrings.get(\"deploymentName\"))) {\n                String fileNameWithoutExtension = fileName.split(\"\\\\.\")[0];\n\n                if (StringUtils.isNotEmpty(fileNameWithoutExtension)) {\n                    fileName = fileNameWithoutExtension;\n                }\n\n                deploymentBuilder.name(fileName);\n                \n            } else {\n                deploymentBuilder.name(decodedQueryStrings.get(\"deploymentName\"));\n            }\n\n            if (decodedQueryStrings.containsKey(\"deploymentKey\") && StringUtils.isNotEmpty(decodedQueryStrings.get(\"deploymentKey\"))) {\n                deploymentBuilder.key(decodedQueryStrings.get(\"deploymentKey\"));\n            }","sourceCodeStart":172,"sourceCodeEnd":208,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-app-engine-rest/src/main/java/org/flowable/app/rest/service/api/repository/AppDeploymentCollectionResource.java#L172-L208","documentation":"Thrown by AppDeploymentCollectionResource.uploadDeployment when the uploaded file's name does not have an accepted extension: only '.app' files (single app definitions) or '.zip' files (handled in the if-branch via ZipInputStream) are accepted. Anything else hits the else branch and is rejected with FlowableIllegalArgumentException.","triggerScenarios":"POST /app-repository/deployments with a file whose name has another extension (e.g. .bar, .bpmn20.xml, .xml, or no extension at all).","commonSituations":"Renaming files without extensions; uploading a process archive (.bar, a BPM-suite convention not accepted here); exporting app definitions without the .app suffix; uppercase extensions if the check is case-sensitive.","solutions":["Upload a file with a .app extension (single app definition) or a .zip containing app definitions.","If you have a .bar or raw XML, package it appropriately first (.app or a zip).","Fix the client's Content-Disposition filename so the extension survives the upload.","Check extension case matches what the code expects (lowercase .app/.zip)."],"exampleFix":"// before\ncurl -F 'file=@myapp.bar' .../app-repository/deployments\n// after\ncp myapp.bar myapp.app\ncurl -F 'file=@myapp.app' .../app-repository/deployments","handlingStrategy":"validation","validationCode":"// Validate the extension before upload\nString name = file.getName().toLowerCase();\nif (!name.endsWith(\".app\") && !name.endsWith(\".zip\")) {\n    throw new IllegalArgumentException(\"Only .app or .zip files are accepted: \" + name);\n}","typeGuard":null,"tryCatchPattern":"try {\n    restTemplate.postForEntity(uploadUrl, requestEntity, AppDeploymentResponse.class);\n} catch (HttpClientErrorException.BadRequest e) {\n    if (e.getResponseBodyAsString().contains(\"must be of type .app\")) {\n        throw new IllegalArgumentException(\"Rename artifact to .app or package it in a .zip\");\n    }\n}","preventionTips":["Standardize on .app (single definition) or .zip (bundle) artifacts.","Do not rename .bar archives without repackaging.","Preserve the filename/extension in Content-Disposition.","Check extension case-sensitivity."],"tags":["validation","upload","file-format","rest"],"backgroundTag":"invalid-argument-value","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}