appwrite/appwrite · error · Appwrite\Extend\Exception
storage_file_type_unsupported
storage_file_type_unsupported
Error message
storage_file_type_unsupported
What it means
Returned synchronously (HTTP 400, code storage_file_type_unsupported) when the uploaded code file's extension is not in the allowed gzip set. The endpoint builds a FileExt validator restricted to FileExt::TYPE_GZIP, so only gzip-family file names (e.g. .tar.gz, .tgz, .gz) pass; a .zip or extension-less file is rejected before size checks.
Source
Thrown at src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php:161
}
$functionSizeLimit = (int) System::getEnv('_APP_COMPUTE_SIZE_LIMIT', '30000000');
if (isset($plan['deploymentSize'])) {
$functionSizeLimit = $plan['deploymentSize'] * 1000 * 1000;
}
$fileExt = new FileExt([FileExt::TYPE_GZIP]);
$fileSizeValidator = new FileSize($functionSizeLimit);
$upload = new Upload();
// Make sure we handle a single file and multiple files the same way
$fileName = (\is_array($file['name']) && isset($file['name'][0])) ? $file['name'][0] : $file['name'];
$fileTmpName = (\is_array($file['tmp_name']) && isset($file['tmp_name'][0])) ? $file['tmp_name'][0] : $file['tmp_name'];
$fileSize = (\is_array($file['size']) && isset($file['size'][0])) ? $file['size'][0] : $file['size'];
if (!$fileExt->isValid($file['name'])) { // Check if file type is allowed
throw new Exception(Exception::STORAGE_FILE_TYPE_UNSUPPORTED);
}
$contentRange = $request->getHeaderLine('content-range');
$deploymentId = ID::unique();
$chunk = 1;
$chunks = 1;
if (!empty($contentRange)) {
$start = $request->getContentRangeStart();
$end = $request->getContentRangeEnd();
$fileSize = $request->getContentRangeSize();
$deploymentId = $request->getHeaderLine('x-appwrite-id', $deploymentId);
// TODO make `end >= $fileSize` in next breaking version
if (is_null($start) || is_null($end) || is_null($fileSize) || $end > $fileSize) {
throw new Exception(Exception::STORAGE_INVALID_CONTENT_RANGE);
}
$chunks = (int) ceil($fileSize / APP_LIMIT_UPLOAD_CHUNK_SIZE);View on GitHub (pinned to 0cefd06153)
Solutions
- Package the deployment as a gzipped tarball: tar -czf code.tar.gz .
- Name the file with a gzip extension (.tar.gz / .tgz / .gz) in the multipart part
- If you have a zip, convert: gunzip is not needed — unzip then tar -czf
- Verify the SDK InputFile keeps the file name with extension
Example fix
# before: zip archive zip -r code.zip . && curl -F 'code=@code.zip' ... # after: gzip tarball tar -czf code.tar.gz . && curl -F 'code=@code.tar.gz' -F 'entrypoint=index.js' -F 'activate=true' ...
Defensive patterns
Strategy: validation
Validate before calling
const GZIP_EXT = /\.(tar\.gz|tgz|gz)$/i;
if (!GZIP_EXT.test(fileName)) throw new Error('package the deployment as a gzip tarball (.tar.gz)');
form.append('code', file, 'code.tar.gz'); Type guard
const isGzipArchive = (name) => /\.(tar\.gz|tgz|gz)$/i.test(name);
Try / catch
try { await functions.createDeployment(functionId, file); } catch (e) { if (e.code === 'storage_file_type_unsupported') { /* repackage as tar.gz and retry */ } else throw e; } Prevention
- Standardize build output on tar -czf code.tar.gz
- Do not send .zip archives to the deployment endpoint
- Verify the SDK preserves the filename extension
When it happens
Trigger: POST /v1/functions/:id/deployments with a file named code.zip, archive.zip, or any name whose extension is not a gzip type; also when the multipart filename loses its extension through SDK misconfiguration.
Common situations: Developers zipping code with zip instead of tar+gzip, CI pipelines producing .zip artifacts, filenames mangled by proxies, or the multipart filename set to a blob without extension.
Related errors
- storage_file_empty
- storage_invalid_content_range
- storage_invalid_file
- general_server_error
- general_server_error
AI-assisted analysis of appwrite/appwrite@0cefd06153 (2026-08-18).
Data as JSON: /api/errors/eeebe4781a3fe9b3.
Report an issue: GitHub.