vuejs Invalid prop: type check failed for prop "modelValue"

Stefan Bogdanescu

Founder & Senior Architect · 2026-06-29

Laravel Company

Resolving the Vue.js Type Mismatch: Mastering File Uploads with v-file-input

As a senior developer working on full-stack applications, dealing with data type mismatches between the backend (Laravel) and the frontend (Vue.js) is a common hurdle. The error you are encountering—Invalid prop: type check failed for prop "modelValue". Expected Array, got String... when using components like v-file-input points directly to an issue in how file data is serialized, transmitted, and bound within your Vue component.

This post will walk through the exact cause of this error in your specific scenario involving image uploads and provide a robust solution for managing file arrays in a Laravel and Vue environment.


Understanding the Type Mismatch Root Cause

The core problem lies in the discrepancy between what the v-file-input component expects and what your backend is sending back.

  1. Vue Expectation: Components designed to handle multiple files (like v-file-input) expect the modelValue prop to be an Array of File objects when dealing with file selection events.
  2. Your Data Flow: In your current setup, your Laravel controller is processing a single uploaded file and storing only its filename ($data->img = $imageName;). When this string is returned to Vue, it is bound to v-model, causing the type check failure because a string is not an array.

The error occurs during the update process because when you try to load data for editing, the model binding expects an array of files to populate the input field, but instead receives a simple string path or filename from the API response.

Backend Review: File Handling in Laravel

The way you handle file storage and retrieval needs refinement, especially when dealing with arrays of files if you anticipate multiple uploads.

In your controller logic:

// Existing Logic Snippet
if ($request->hasFile('img')) {
    $image = $request->file('img')[0]; // Only accessing the first file
    $imageName = time() . '.' . $image->getClientOriginalExtension();
    try {
        $image->storeAs('public/images/categories', $imageName);
        $data->img = $imageName; // Storing only a string filename
    } catch (Exception $e) {
        // ... error handling
    }
}

If you intend to handle multiple files, or if the frontend expects an array of file data for updates, you must ensure the API response reflects that structure. When dealing with complex resource relationships in Laravel, understanding how Eloquent models interact with file storage is crucial, as demonstrated by best practices often discussed on platforms like laravelcompany.com.

Frontend Solution: Binding File Arrays Correctly

To resolve this, you need to ensure that when data is fetched (getResults()) or when data is prepared for editing, the data passed to v-model is an array structure that Vue can correctly interpret as files.

1. Adjusting Data Fetching (getResults()):

If your goal is simply to display existing images based on stored filenames, you should fetch the filenames (strings) and handle the image path construction client-side, as you are already doing in your v-img tag:

// Ensure data fetched from API contains filenames (strings) for display
this.allData = response.data; 
// ... this part seems fine if 'img' stores just the filename string.

2. Handling File Updates (editDataModel):

The error arises when you try to populate the input field with existing data or prepare for a new upload. Since v-file-input is primarily for selecting new files, you need a mechanism to manage the array of files being edited.

When preparing to edit a record, instead of trying to bind an existing string model value to a file input meant for selection, focus on managing the actual file objects or paths separately.

Best Practice for Updates:
If you are updating image references, ensure your API endpoint accepts an array of file uploads (using multipart/form-data) and that the Vue side correctly maps these files into an array structure before sending them:

// Example conceptual update logic in Vue
methods: {
    editDataModel(data) {
        // If you are loading existing data, load the stored filename into a separate field
        this.currentImage = data.img; 
        // The v-file-input should then be used for *new* uploads, not binding the old string directly to modelValue unless that input is specifically designed for file selection only.
    }
}

For direct file interaction via v-file-input, ensure that any data bound to it (like modelValue) is explicitly initialized as an empty array ([]) when the component loads, and only populated with actual File objects returned from a successful file selection event. This prevents Vue from attempting to bind a non-array string value to a prop expecting an array of files.

Conclusion

The "Invalid prop: type check failed" error is a classic symptom of mismatched data types between the server's response (string) and the client's component expectation (array/File object). By carefully reviewing your API contracts—ensuring that file uploads are handled as multi-part data if multiple files are expected, and that stored database values are correctly mapped to Vue arrays—you can seamlessly manage complex file interactions in your application. Always strive for strict type consistency between Laravel and Vue components.