octobercms/october · error · ApplicationException
There is no file attached to import!
Error message
There is no file attached to import!
What it means
ThemeImport::import() resolves the attached archive through the uploaded_file deferred relation with the provided $sessionKey. If no file model is returned, it throws - meaning the import ran without a zip ever being attached, or the deferred binding was invisible because the session key was wrong, missing, or the upload session expired.
Source
Thrown at modules/cms/models/ThemeImport.php:113
$this->attributes['themeName'] = $theme->getConfigValue('name', $theme->getDirName());
$this->attributes['dirName'] = $theme->getDirName();
$this->attributes['theme'] = $theme;
}
/**
* import
*/
public function import($theme, $data = [], $sessionKey = null)
{
@set_time_limit(3600);
$this->theme = $theme;
$this->fill($data);
try {
$file = $this->uploaded_file()->withDeferred($sessionKey)->first();
if (!$file) {
throw new ApplicationException('There is no file attached to import!');
}
$themePath = $this->theme->getPath();
$tempPath = temp_path() . '/'.uniqid('oc');
$zipName = uniqid('oc');
$zipPath = temp_path().'/'.$zipName;
File::put($zipPath, $file->getContents());
if (!File::makeDirectory($tempPath)) {
throw new ApplicationException('Unable to create directory '.$tempPath);
}
Zip::extract($zipPath, $tempPath);
if (File::isDirectory($tempPath.'/meta')) {
$this->copyDirectory($tempPath.'/meta', $themePath.'/meta');
}View on GitHub (pinned to b608633a7e)
Solutions
- Attach the zip in the import form and confirm the upload widget finished successfully before clicking Import.
- When calling import() programmatically, pass the exact session key the upload used - the same value the fileupload widget reports as sessionKey.
- Guard before importing: $import->uploaded_file()->withDeferred($sessionKey)->first() must return a file.
- If the session expired, restart the wizard from upload.
Example fix
// before: wrong key - deferred binding invisible, import throws $themeImport->import($theme, $data, $otherKey); // after: reuse the key the file was deferred-bound under $themeImport->import($theme, $data, $fileWidget->sessionKey);
Defensive patterns
Strategy: validation
Validate before calling
$file = $themeImport->uploaded_file()->withDeferred($sessionKey)->first();
if (!$file) {
// show 'select a zip file' validation error before import() runs
} Try / catch
try {
$themeImport->import($theme, $data, $sessionKey);
} catch (ApplicationException $e) {
// re-prompt the upload step; typically a lost/wrong session key
} Prevention
- Mark the file field required in the import form.
- Forward the fileupload widget's sessionKey through every AJAX handler in the wizard.
- Restart the wizard if the session expires - deferred bindings die with it.
When it happens
Trigger: Submitting the theme import form without selecting a file; calling import($theme, $data, $sessionKey) with a $sessionKey that differs from the one the fileupload widget used when binding the file; a deferred binding flushed or session lost between upload and import.
Common situations: Custom AJAX import handlers that forget to forward the widget session key; user leaving the import wizard open past session lifetime; the file upload failing silently (size limits) so the relation stays empty.
Related errors
AI-assisted analysis of octobercms/october@b608633a7e (2026-08-21).
Data as JSON: /api/errors/b50ce92ddc9d3d61.
Report an issue: GitHub.