"Non-function value encountered for default slot." in Vue 3 Composition API component

To resolve the error "Non-function value encountered for default slot." in a Vue 3 Composition API component, you can follow these steps:

  1. Check your component's template for any default slots that are expecting a function but receiving a non-function value instead. Default slots in Vue expect functions as their values.
  2. Inspect the component's usage to ensure that you are passing a function to the default slot. If you're passing a variable or a non-function value, it could lead to this error.
  3. If you're using a template syntax like <template>, ensure that the default slot's value is indeed a function. For example:
    {{ slotValue }}

import { defineComponent } from 'vue';

export default defineComponent({
  setup() {
    const slotValue = () => {
      // Your slot logic here

    return { slotValue };

Make sure that slotValue is indeed a function in the setup function.

The following might not help the original poster of the question as they seem to have already solved their issue. However, I wanted to share that I encountered the same warning message because I was using a component and instead of having its closing tag just at its end - i.e. <v-select ...misc props...></v-select>, I decided to align the closing tag with the opening one, i.e.:

<v-select  ...misc props...
           ...and event handlers...  >

This creates a text node (and thus content for the default slot) between the > and the <.

Changing to either:

<v-select  ...misc props...
           ...and event handlers...  ></v-select>


<v-select  ...misc props...
           ...and event handlers...  

solves the issue, and the warning is not displayed anymore.

The correct solution to hide this warning is to change array children to:

  default: () => children,

For your example, it must be changed to this:

return () =>
  h(HelloWorld, {}, {
    default: () => [h("div", {}, ["Div 1"]), h("div", {}, ["Div 2"])],

Instead of rendering the child slot directly in the parent component (i.e., passing an array of VNodes as the slots argument directly), wrap it in a function:

// src/components/Composite.js
export default defineComponent({
  setup(props, { slots }) {
    return () =>          👇
      h(HelloWorld, {}, () => [h("div", {}, ["Div 1"]), h("div", {}, ["Div 2"])]);

Note that the inner h() calls don't need this function wrapper because they're all rendered together with the default slot by the child component.