Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

muuucho's avatar
Level 11

Can't upload a file in Livewire

When I try to upload a file using a form a get the error: "Trying to access array offset on null" Why is that?

<?php

namespace App\Livewire\Uploads;

use App\Models\AttestRule;
use App\Models\Invoice;
use Auth;
#use Illuminate\Console\View\Components\Alert;
use Livewire\Component;
use Illuminate\Contracts\View\View;
use Illuminate\Validation\Rule;
use Jantinnerezo\LivewireAlert\LivewireAlert;
use Livewire\WithFileUploads;

class Form extends Component
{
    use WithFileUploads;
    use LivewireAlert;
    public ?Invoice $invoice = null;
    public string $file = '';

    public function save() // Methods are called Actions. They do things, like after a form submit that has wire:submit
    {
        $this->validate();
        $filename = $this->image->store('invoices', 'public'); // Store the file into the folder invoices in public
        if (is_null($this->invoice)) {
            $this->invoice = Invoice::create(
                [
                    'team_id' => Auth::user()->team_id,
                    'cb' => Auth::id(),
                    'ub' => Auth::id(),
                    'ua' => now(),
                    'file' => $filename,
                ]
            );
        }
        $this->flash('success', 'Post successfully uploaded');
        return redirect()->to('/invoices');
    }

    public function rules(): array
    {
        return [
            'file' => 'required|mimes:pdf,jpg,png|max:2048',
        ];
    }

    public function render(): View
    {
        return view('livewire.uploads.form');
    }
}

<div>
    <div class="py-6">
        <div class="mx-auto max-w-7xl sm:px-6 lg:px-8">
            <div class="overflow-hidden bg-white shadow-sm sm:rounded-lg">
                <div class="p-6 bg-white border-b border-gray-200">
                    <div class="flex justify-between items-center">
                        <div><x-section-header>Upload an invoice</x-section-header></div>
                        <div class="mb-3">
                            <x-primary-link :href="route('uploads.all')">
                                <x-icon-link icon="o-arrow-left"/>Cancel
                            </x-primary-link>
                        </div>
                    </div>
                    <form wire:submit="save" enctype="multipart/form-data">
                        @csrf
                        <div>
                            <x-input-label for="file" :value="__('Invoice')" />
                            <x-text-input wire:model="file" id="file" class="block mt-1 w-full" type="file"/>
                            <x-input-error :messages="$errors->get('file')" class="mt-2" />
                        </div>
                        <div class="mt-4">
                            <x-primary-button type="submit">
                            <x-icon-link icon="o-circle-stack"/>Save
                            </x-primary-button>
                        </div>
                    </form>
                    <div wire:loading class="absolute inset-0 bg-white opacity-50"></div>
                    <div wire:loading.delay>
                        <div wire:loading.flex class="flex justify-center items-center absolute inset-0">
                            <x-icon-spinner/>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
@push('js')
@endpush

0 likes
15 replies
LaryAI's avatar
Level 58

The error "Trying to access array offset on null" typically occurs when you try to access an array element that doesn't exist. In your case, it seems to be related to the file upload process in Livewire.

Here are a few steps to troubleshoot and fix the issue:

  1. Ensure the File Input is Correctly Bound: Make sure the file input is correctly bound to the Livewire property. In your form, you have:

    <x-text-input wire:model="file" id="file" class="block mt-1 w-full" type="file"/>
    

    This should be fine, but ensure that the wire:model is correctly set to file.

  2. Check the Property Type: The property public string $file = ''; should be changed to public $file; because it will hold an instance of the uploaded file, not a string.

  3. Update the Validation Rule: Ensure that the validation rule matches the property type. You have:

    'file' => 'required|mimes:pdf,jpg,png|max:2048',
    

    This is correct, but make sure the property type is not causing issues.

  4. Store the Uploaded File: In your save method, you are trying to store the file using $this->image->store('invoices', 'public');. However, the property is named file, not image. Update this line to:

    $filename = $this->file->store('invoices', 'public');
    
  5. Ensure File Uploads are Enabled: Make sure you have included the WithFileUploads trait in your component, which you have done correctly.

Here is the updated code for your Livewire component:

namespace App\Livewire\Uploads;

use App\Models\AttestRule;
use App\Models\Invoice;
use Auth;
use Livewire\Component;
use Illuminate\Contracts\View\View;
use Illuminate\Validation\Rule;
use Jantinnerezo\LivewireAlert\LivewireAlert;
use Livewire\WithFileUploads;

class Form extends Component
{
    use WithFileUploads;
    use LivewireAlert;

    public ?Invoice $invoice = null;
    public $file; // Change from string to a generic type

    public function save()
    {
        $this->validate();

        // Store the file into the folder invoices in public
        $filename = $this->file->store('invoices', 'public');

        if (is_null($this->invoice)) {
            $this->invoice = Invoice::create([
                'team_id' => Auth::user()->team_id,
                'cb' => Auth::id(),
                'ub' => Auth::id(),
                'ua' => now(),
                'file' => $filename,
            ]);
        }

        $this->flash('success', 'Post successfully uploaded');
        return redirect()->to('/invoices');
    }

    public function rules(): array
    {
        return [
            'file' => 'required|mimes:pdf,jpg,png|max:2048',
        ];
    }

    public function render(): View
    {
        return view('livewire.uploads.form');
    }
}

And ensure your Blade template remains the same, as it looks correct:

<div>
    <div class="py-6">
        <div class="mx-auto max-w-7xl sm:px-6 lg:px-8">
            <div class="overflow-hidden bg-white shadow-sm sm:rounded-lg">
                <div class="p-6 bg-white border-b border-gray-200">
                    <div class="flex justify-between items-center">
                        <div><x-section-header>Upload an invoice</x-section-header></div>
                        <div class="mb-3">
                            <x-primary-link :href="route('uploads.all')">
                                <x-icon-link icon="o-arrow-left"/>Cancel
                            </x-primary-link>
                        </div>
                    </div>
                    <form wire:submit="save" enctype="multipart/form-data">
                        @csrf
                        <div>
                            <x-input-label for="file" :value="__('Invoice')" />
                            <x-text-input wire:model="file" id="file" class="block mt-1 w-full" type="file"/>
                            <x-input-error :messages="$errors->get('file')" class="mt-2" />
                        </div>
                        <div class="mt-4">
                            <x-primary-button type="submit">
                                <x-icon-link icon="o-circle-stack"/>Save
                            </x-primary-button>
                        </div>
                    </form>
                    <div wire:loading class="absolute inset-0 bg-white opacity-50"></div>
                    <div wire:loading.delay>
                        <div wire:loading.flex class="flex justify-center items-center absolute inset-0">
                            <x-icon-spinner/>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
@push('js')
@endpush

These changes should resolve the error and allow you to upload files using Livewire.

muuucho's avatar
Level 11

Nothing of this helped. The error appears before even posting the form. It happens just after I chose the file for the upload.

muuucho's avatar
Level 11

@snapey Do you mean something like dump($errors) Where in the code should I dump it? The error log says: "Trying to access array offset on null {"userId":1,"exception":"[object] (ErrorException(code: 0): Trying to access array offset on null at C:\xampp\htdocs\livewire\vendor\livewire\livewire\src\Features\SupportFileUploads\WithFileUploads.php:73) [stacktrace]"

EDIT: I found this in my Debugbar:

{
    "_token": "mNPL80F5MU1fZH2cjfy1QeiupO2bmUEQVgGWiVyp",
    "components": [
        {
            "snapshot": "{\"data\":{\"invoice\":null,\"file\":\"\"},\"memo\":{\"id\":\"FsCBZV5NtIKHZNeUzlAc\",\"name\":\"uploads.form\",\"path\":\"uploads\/create\",\"method\":\"GET\",\"children\":[],\"scripts\":[],\"assets\":[],\"errors\":[],\"locale\":\"en\"},\"checksum\":\"9ee21ebb51737593db0039306aec84d189192208390ccf4c242e06331e4146c6\"}",
            "updates": [],
            "calls": [
                {
                    "path": "",
                    "method": "_uploadErrored",
                    "params": [
                        "file",
                        "<br />\n<b>Warning</b>:  File upload error - unable to create a temporary file in <b>Unknown</b> on line <b>0</b><br />\n{\"message\":\"The files.0 failed to upload.\",\"errors\":{\"files.0\":[\"The files.0 failed to upload.\"]}}",
                        false
                    ]
                }
            ]
        }
    ]
}

What temporary file? And where can I define the path that seems to be missing?

Snapey's avatar

@muuucho no I mean show us the complete error with stack trace so that we at least know what line is throwing the error

muuucho's avatar
Level 11

OK the stack says that the error occours in C:\xampp\htdocs\livewire\public\index .PHP: 51

$response = $kernel->handle(  // Row 51

    $request = Request::capture()

)->send();
jlrdw's avatar

@muuucho Are you correctly pointing to public as the document root.

muuucho's avatar
Level 11

@jlrdw Like you see below, I am now on a completely fresh Laravel installation. Do I still need to do some further pointing? If so, how?

muuucho's avatar
Level 11

Hm, I started from scratch, just to avoid any strange settings from my side earlier in the project. So, on PHP 8.3.7 I Installed Laravel 11.13.0 and Livewire 3.5 Then I ran php artisan livewire:make UploadPhoto After that I pasted in the code from to the component directly from the docs: https://livewire.laravel.com/docs/uploads I added a render method and created the route Route::get('/photo', UploadPhoto::class); Then I created views/components/layouts/app.blade.php If I now visit "http://localhost:8000/photo" I see the ugly form and when I choose a 150k pdf file to upload I get the error: Trying to access array offset on null. The error appears in C:\xampp\htdocs\file-upload\vendor\livewire\livewire\src\Features\SupportFileUploads\WithFileUploads.php :73 I get the error just after picking the file, before hitting Submit.

<?php

use App\Livewire\UploadPhoto;
use Illuminate\Support\Facades\Route;

Route::get('/', function () {
    return view('welcome');
});

Route::get('/photo', UploadPhoto::class);
<html>
<head>
    @livewireStyles
</head>
<body>
<main>
    {{ $slot }}
</main>
@livewireScripts
</body>
</html>
<div>
    <form wire:submit="save">

        <input type="file" wire:model="photo">

        @error('photo') <span class="error">{{ $message }}</span> @enderror

        <button type="submit">Save photo</button>
    </form>
</div>
<?php

namespace App\Livewire;

use Livewire\Component;
use Livewire\WithFileUploads;
use Livewire\Attributes\Validate;

class UploadPhoto extends Component
{
    use WithFileUploads;

    #[Validate('image|max:1024')] // 1MB Max
    public $photo;

    public function save()
    {
        $this->photo->store(path: 'photos');
    }
    public function render()
    {
        return view('livewire.upload-photo');
    }
}


UPDATE: If I halt the script before validation by writing die(''), I get "Warning: File upload error - unable to create a temporary file in Unknown on line 0".

UPDATE2: If halt and instead dump $request->all(), I get:

array:2 [▼ // app\Http\Controllers\FileController.php:13
  "_token" => "ybVVTqpdszKPThS1obg9P1dAXqHsn2QLUVyw91dl"
  "file" => 
Illuminate\Http
\
UploadedFile {#401 ▼
    -test: false
    -originalName: "file-sample_150kB.pdf"
    -mimeType: "application/octet-stream"
    -error: 6
    -originalPath: "file-sample_150kB.pdf"
    #hashName: null
    path: ""
    filename: ""
    basename: ""
    pathname: ""
    extension: ""
    realPath: "C:\xampp\htdocs\file-upload\public"
    aTime: 1970-01-01 00:00:00
    mTime: 1970-01-01 00:00:00
    cTime: 1970-01-01 00:00:00
    inode: false
    size: false
    perms: 00
    owner: false
    group: false
    type: false
    writable: false
    readable: false
    executable: false
    file: false
    dir: false
    link: false
  }
]
muuucho's avatar
Level 11

I've cleared Chromes cash and removed all cookies. Still the same error. Laravel debug throws:

? str_ireplace('files', $name, $errorsInJson)
            : str_ireplace('files.0', $name, $errorsInJson);

        $errors = json_decode($errorsInJson, true)['errors'];

        throw (ValidationException::withMessages($errors));
    }

I also tried Mozilla, same error. And I turned Windows security off. Same problem I am stucked.

muuucho's avatar
Level 11

Now, I installed a new Laravel project in Herd, and it works! Still I wonder, and needs to solve, why it is not working when I don't use Herd.

jchown@successtech.com's avatar

@muuucho Not sure what local server configuration you were using before Herd, but maybe ‘php artisan storage:link’ was needed (as it would be on a production server) for the upload to work.

muuucho's avatar
Level 11

@[email protected] Thanks, I tried with and without this linking, the error remains. Since I don't even reach the validation, the problem probably occurs earlier. I've been searching for chrome and windows issues and did some clearing of cache and cookies, but without finding a solution. My plan now is to move everything to Herd.

KaiyouS's avatar

Any update on this? mine also throws the same error if I don't use Herd. I am using Spatie Media Library.

Snapey's avatar

check your php settings. In Herd you are using different values

Please or to participate in this conversation.