Skip to main content
New to LiveVue? Start with Quickstart for a working example, then check Basic usage for common patterns.

Component issues

Component not rendering

Symptoms:
  • Empty div where component should be
  • No errors in console
  • Component works in isolation
Possible causes and solutions: 1. Missing v-socket attribute
# ❌ Missing v-socket
<.vue v-component="Counter" count={@count} />

# ✅ Correct
<.vue v-component="Counter" count={@count} v-socket={@socket} />
2. Component name mismatch
# ❌ File: Counter.vue, but using wrong name
<.vue v-component="counter" v-socket={@socket} />

# ✅ Correct - case sensitive
<.vue v-component="Counter" v-socket={@socket} />
Check browser console for errors. 3. Component not found in resolution
// Check your component resolution in assets/vue/index.js
const components = {
  ...import.meta.glob("./**/*.vue", { eager: true }),
}

// Debug: log available components
console.log("Available components:", Object.keys(components))

Component renders but doesn’t update

Symptoms:
  • Component shows initial state
  • Props don’t update when server state changes
  • No reactivity
Solutions: 1. Check prop names match
# Server side
<.vue user_name={@user.name} v-component="Profile" v-socket={@socket} />
<!-- Client side - prop names must match exactly -->
<script setup>
const props = defineProps<{
  user_name: string  // Must match server prop name
}>()
</script>
2. Verify assigns are updating
# Add debug logging
def handle_event("update", _params, socket) do
  IO.inspect(socket.assigns, label: "Before update")
  socket = assign(socket, :count, socket.assigns.count + 1)
  IO.inspect(socket.assigns, label: "After update")
  {:noreply, socket}
end
3. Use Vue.js devtools to inspect the component Open Vue.js devtools in browser and inspect the component. Check if the component is receiving the correct props and re-rendering when the props change.

LiveVue.Encoder protocol issues

Symptoms:
  • Protocol.UndefinedError when passing structs as props
  • Component doesn’t render with custom struct props
  • Error mentions “LiveVue.Encoder protocol must always be explicitly implemented”
Solutions: 1. Implement the encoder protocol for your structs
defmodule User do
  @derive LiveVue.Encoder
  defstruct [:name, :email, :age]
end
2. For third-party structs, use Protocol.derive/3
# In your application.ex or relevant module
Protocol.derive(LiveVue.Encoder, SomeLibrary.User, only: [:id, :name])
3. Debug encoder issues
# Test your encoder implementation
iex> user = %User{name: "John", email: "[email protected]"}
iex> LiveVue.Encoder.encode(user)
%{name: "John", email: "[email protected]"}
For complete implementation details including field selection and custom implementations, see Basic usage. Common causes:
  • Passing structs without implementing the encoder protocol
  • Nested structs where some don’t have the protocol implemented
  • Third-party library structs that need protocol derivation

TypeScript errors

Common error: Cannot find module 'live_vue'
// Add to your env.d.ts or types.d.ts
declare module 'live_vue' {
  export function useLiveVue(): any
  export function createLiveVue(config: any): any
  export function findComponent(components: any, name: string): any
  export function getHooks(app: any): any
}
Error: Property 'xxx' does not exist on type
// Define proper interfaces
interface Props {
  count: number
  user: {
    id: number
    name: string
  }
}

const props = defineProps<Props>()

Event handling issues

Events not firing

Symptoms:
  • Clicking buttons does nothing
  • No events reach LiveView
  • Console shows no errors
Solutions: 1. Check event handler syntax
# ❌ Wrong syntax
<.vue v-on-click={JS.push("increment")} />

# ✅ Correct syntax
<.vue v-on:click={JS.push("increment")} />
2. Verify event names match
<!-- Vue component -->
<button @click="$emit('increment', {amount: 1})">+1</button>
<!-- LiveView template -->
<.vue v-on:increment={JS.push("inc")} />

def handle_event("inc", %{"amount" => amount}, socket) do
  # Handle event
end
3. Check payload structure
# Debug event payload
def handle_event("save", params, socket) do
  IO.inspect(params, label: "Event params")
  {:noreply, socket}
end

Events fire but handler not called

Check handler function exists:
# Make sure you have the handler defined
def handle_event("my_event", _params, socket) do
  {:noreply, socket}
end
Verify event name spelling:
# Event names are case-sensitive
<.vue v-on:save-user={JS.push("save_user")} />  # save-user → save_user

Build and development issues

Vite server not starting

Error: EADDRINUSE: address already in use
# Kill process using port 5173
lsof -ti:5173 | xargs kill -9

# Or use different port
npm run dev -- --port 5174
Error: Module not found
# Clear node_modules and reinstall
rm -rf node_modules package-lock.json
npm install

Build failures

TypeScript compilation errors:
# Check TypeScript version compatibility
npm install [email protected] [email protected]
Vite build errors:
# Clear Vite cache
rm -rf node_modules/.vite
npm run build

Hot reload not working

1. Check Vite configuration:
// vite.config.js
export default defineConfig({
  server: {
    host: '0.0.0.0',  // Allow external connections
    port: 5173,
    hmr: true
  }
})
2. Verify watcher configuration:
# config/dev.exs
config :my_app, MyAppWeb.Endpoint,
  watchers: [
    npm: ["--silent", "run", "dev", cd: Path.expand("../assets", __DIR__)]
  ]
3. Understand HMR scope:
  • Vue files: Hot Module Replacement works seamlessly - changes to .vue files are reflected instantly without page refresh
  • Elixir files: Changes to .ex and .heex files trigger a LiveView re-render via Phoenix’s code reloading, not Vite HMR. This still provides fast feedback but works through LiveView’s WebSocket connection rather than Vite’s HMR

SSR issues

SSR not working

Check SSR configuration:
# config/dev.exs
config :live_vue,
  ssr_module: LiveVue.SSR.ViteJS,
  vite_host: "http://localhost:5173",
  ssr: true
For complete SSR configuration options, see Configuration. Verify Node.js version:
node --version  # Should be 19+

SSR errors in production

Check NodeJS supervisor:
# application.ex
children = [
  {NodeJS.Supervisor, [path: LiveVue.SSR.NodeJS.server_path(), pool_size: 4]},
  # ... other children
]
Verify server bundle exists:
ls priv/static/server.mjs  # Should exist after build
For production SSR setup details, see Configuration.

Performance issues

Slow initial load

1. Enable lazy loading:
// assets/vue/index.js
const components = {
  Counter: () => import('./Counter.vue'),
  Modal: () => import('./Modal.vue')
}
2. Optimize bundle size:
# Analyze bundle
npm run build -- --analyze

Memory leaks

Clean up event listeners:
<script setup>
import { onUnmounted } from 'vue'
import { useLiveVue } from 'live_vue'

const live = useLiveVue()

const cleanup = live.handleEvent('data_update', handleUpdate)

onUnmounted(() => {
  cleanup()  // Important: clean up listeners
})
</script>
Clear timers and intervals:
<script setup>
import { onUnmounted } from 'vue'

const interval = setInterval(() => {
  // Do something
}, 1000)

onUnmounted(() => {
  clearInterval(interval)
})
</script>

Debugging techniques

Enable debug mode

// In browser console or app.js
window.liveVueDebug = true

Component inspection

1. Use Vue DevTools browser extension 2. Add debug logging:
<script setup>
import { watch } from 'vue'

const props = defineProps<{count: number}>()

watch(() => props.count, (newVal, oldVal) => {
  console.log('Count changed:', oldVal, '→', newVal)
})
</script>

Network debugging

1. Monitor WebSocket traffic in browser DevTools 2. Log LiveView events:
def handle_event(event, params, socket) do
  IO.inspect({event, params}, label: "LiveView Event")
  # ... handle event
end

Common error messages

Cannot read property 'mount' of undefined

Cause: Component resolution failed Solution: Check component name and file path
// Debug component resolution
// find component does it by default, you might need to do it if you override it
console.log("Resolving component:", componentName)
console.log("Available components:", Object.keys(components))

ReferenceError: process is not defined

Cause: Node.js globals in browser code Solution: Add to Vite config:
// vite.config.js
export default defineConfig({
  define: {
    global: 'globalThis',
    'process.env': {}
  }
})

Module "live_vue" has been externalized

Cause: SSR configuration issue Solution: Check Vite SSR config:
// vite.config.js
export default defineConfig({
  ssr: {
    noExternal: ['live_vue']
  }
})

Getting help

Before asking for help

  1. Check browser console for errors
  2. Verify all configuration steps (see Configuration)
  3. Test with minimal reproduction case
  4. Create a fresh project with Igniter to verify the issue isn’t in your configuration

Where to get help

  1. GitHub Issues: For bugs and feature requests
  2. GitHub Discussions: For questions and community help
  3. Elixir Forum: For general Phoenix/Elixir questions
  4. Vue.js Discord: For Vue-specific questions

Creating bug reports

Include:
  1. LiveVue version
  2. Phoenix/LiveView versions
  3. Node.js version
  4. Minimal reproduction case
  5. Error messages and stack traces
  6. Browser and OS information

Next steps

Build docs developers (and LLMs) love