Debugging and common pitfalls
Most Alpine errors come down to three causes: a typo in an expression, the wrong startup order, and elements that are visible before Alpine starts. Here is how to recognize and fix them.
Console messages
When an expression in a directive fails, Alpine logs an "Alpine Expression Error" warning with the error text, the expression and the element:
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
<div x-data="{ tasks: ['Buy milk'] }">
<p x-text="taks.length"></p>
</div>Below the example you see the error: taks is not defined and the expression taks.length. A typo in a name is the most common cause. In the browser, open the developer tools console: there the message is clickable and leads to the element.
x-cloak: flicker on load
The Alpine script runs after the browser has displayed the HTML. Elements with x-show="false" can flash for a split second: a modal or a menu appears and disappears. The x-cloak directive hides an element until Alpine starts — Alpine removes it on start. But you have to add the CSS rule for it yourself:
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
<style>
[x-cloak] { display: none !important; }
</style>
<div x-data="{ open: false }">
<button @click="open = !open">Menu</button>
<ul x-show="open" x-cloak>
<li>Edit</li>
<li>Delete</li>
</ul>
</div>The menu does not show up while the page loads, even on a slow connection. The [x-cloak] rule goes into the site's shared CSS in the <head>, and x-cloak goes on everything hidden by default.
Startup order
| Symptom | Cause | Fix |
|---|---|---|
| Directives do nothing at all | The script has no defer, or Alpine.start() is not called | Add defer, call Alpine.start() |
todos is not defined | Alpine.data registered after start | Register in alpine:init or before Alpine.start() |
| A plugin does nothing | The plugin script is below Alpine | Load plugins above Alpine |
| Everything fires twice | Alpine is loaded twice | Keep one way of loading |
Inspecting component data
To see what is in the data right now, print it on the page. JSON.stringify from the "JSON" lesson of the tutorial makes the object readable:
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
<div x-data="{ title: '', tasks: ['Buy milk'] }">
<input x-model="title" placeholder="New task">
<pre x-text="JSON.stringify({ title, tasks }, null, 2)"></pre>
</div>The <pre> block shows the component's data and updates as you type. In the browser console, Alpine.$data(element) gives the same. There are also browser extensions, such as Alpine.js devtools, that show the component tree.
Common mistake
Adding x-cloak but forgetting the CSS rule. The attribute alone hides nothing — it is a plain attribute that Alpine removes on start. Without the [x-cloak] { display: none !important; } rule the flicker stays. If the rule is there but the element never appears, check that Alpine started at all: most likely the script did not load.