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

  1. Attach the zip in the import form and confirm the upload widget finished successfully before clicking Import.
  2. When calling import() programmatically, pass the exact session key the upload used - the same value the fileupload widget reports as sessionKey.
  3. Guard before importing: $import->uploaded_file()->withDeferred($sessionKey)->first() must return a file.
  4. 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

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.