Fix: Invalid Prop Name Is a Reserved Property in Vue.js

Error message:
Invalid prop name: "{key}" is a reserved property.
Props & Properties 2025-01-25

What Causes This Warning?

This warning occurs when you try to use a reserved property name as a prop. Vue reserves certain property names for internal use, such as key, ref, $, and properties starting with _.

The Problem

<script setup>
// ❌ Using reserved prop names
defineProps({
  key: String,      // Reserved by Vue for list rendering
  ref: String,      // Reserved for template refs
  $data: Object,    // $ prefix is reserved
  _internal: String // _ prefix is reserved
})
</script>

The Fix

Use Different Prop Names

<script setup>
// ✅ Use non-reserved names
defineProps({
  itemKey: String,    // Instead of 'key'
  reference: String,  // Instead of 'ref'
  dataObject: Object, // Instead of '$data'
  internal: String    // Instead of '_internal'
})
</script>

Reserved Property Names

These names are reserved and cannot be used as props:

Reserved NameWhy Reserved
keyUsed for list rendering (v-for)
refUsed for template refs
$elInstance property
$dataInstance property
$propsInstance property
$attrsInstance property
$refsInstance property
$slotsInstance property
$parentInstance property
$rootInstance property
$emitInstance method
$watchInstance method
$forceUpdateInstance method
$nextTickInstance method
_*Internal Vue properties

Common Scenarios

List Item Component

<!-- ❌ Wrong - 'key' is reserved -->
<script setup>
defineProps({
  key: String,
  value: String
})
</script>

<!-- ✅ Correct -->
<script setup>
defineProps({
  itemKey: String,
  value: String
})
</script>

<!-- Parent usage -->
<template>
  <ListItem
    v-for="item in items"
    :key="item.id"
    :item-key="item.id"
    :value="item.name"
  />
</template>

Reference Prop

<!-- ❌ Wrong -->
<script setup>
defineProps({
  ref: Object // Reserved!
})
</script>

<!-- ✅ Correct -->
<script setup>
defineProps({
  reference: Object,
  // or
  elementRef: Object,
  // or
  targetRef: Object
})
</script>

Data Object Prop

<!-- ❌ Wrong -->
<script setup>
defineProps({
  $data: Object
})
</script>

<!-- ✅ Correct -->
<script setup>
defineProps({
  data: Object,
  // or
  modelData: Object,
  // or
  formData: Object
})
</script>

Private/Internal Props

<!-- ❌ Wrong - _ prefix is reserved -->
<script setup>
defineProps({
  _config: Object,
  _internal: Boolean
})
</script>

<!-- ✅ Correct -->
<script setup>
defineProps({
  config: Object,
  isInternal: Boolean
  // or use a different naming convention
})
</script>

When You Need Similar Names

<script setup>
// If you're wrapping a component that expects 'key'
// Use a different name and map it

const props = defineProps({
  itemKey: String
})

// Use itemKey internally but pass as needed
</script>

<template>
  <!-- Pass to native element or third-party component -->
  <div :data-key="itemKey">
    {{ itemKey }}
  </div>
</template>

TypeScript Considerations

// Type definitions should also avoid reserved names
interface Props {
  // ❌ These would conflict
  // key: string
  // ref: HTMLElement

  // ✅ Use alternative names
  itemKey: string
  elementRef: HTMLElement
}

defineProps<Props>()

Quick Checklist

  • Don’t use key or ref as prop names
  • Avoid $ prefix for prop names
  • Avoid _ prefix for prop names
  • Use descriptive alternatives like itemKey, reference
  • Check Vue instance properties for other reserved names
  • Update parent components when renaming props