ANTIGRAVITY LABJP
Articles/App Development
App Development/2026-04-28Intermediate

Diagnosing and Fixing HMR (Hot Reload) Failures in Antigravity

A practical, step-by-step diagnostic for hot module replacement failures in Antigravity, covering file watchers, ports and proxies, build-tool config, and editor-specific quirks.

antigravity346hmrhot-reloadtroubleshooting102nextjs4vite

"I'm saving the file, but the browser refuses to update." "HMR works once and then goes silent." If you've spent any meaningful time in Antigravity with Next.js or Vite, this scene probably feels familiar. I run into it constantly while maintaining the four sites that make up Dolice Labs, especially right after letting an AI agent rewrite a chunk of the codebase.

The frustrating part is that broken HMR isn't one bug — it's a category of bugs that span four different layers: the file watcher, the network path between server and browser, the build tool's own configuration, and Antigravity-specific behavior. Trying to fix it by intuition alone is a great way to lose an afternoon. What follows is the diagnostic order I actually use, plus the fixes for each layer. By the end, you should have at least one new "next thing to try" in your toolkit.

Start by classifying the symptom

HMR problems present in three fairly distinct ways, and each points to a different root cause. Before you touch a config file, decide which of these you're seeing:

  • Symptom A: The terminal still prints compiled successfully, but the browser stays silent.
  • Symptom B: Saving the file produces no terminal output at all — the build never starts.
  • Symptom C: HMR works fine for the first few minutes, then suddenly stops.

In my experience, Symptom A is almost always a network-path issue, Symptom B is a file-watcher issue, and Symptom C is a resource-exhaustion issue. Picking the right starting point saves a surprising amount of time.

Symptom A: Only the browser is unresponsive

If the dev server is happily compiling but the browser doesn't pick up the change, the WebSocket channel that delivers HMR updates is being dropped somewhere along the way.

Open your browser's DevTools and check the Console and Network tabs. A red line like WebSocket connection to 'ws://localhost:3000/_next/webpack-hmr' failed is the smoking gun.

# Run inside Antigravity's integrated terminal
# Verify the HMR WebSocket port is actually listening
lsof -i -P | grep LISTEN | grep -E "3000|3001|24678"
# Expected output (example):
# node    12345 ...    TCP *:3000 (LISTEN)

There are three fixes I reach for, in order. First, when working over a remote workspace, Antigravity's port forwarder occasionally fails to proxy the WebSocket frame even though the HTTP traffic flows fine. Open the command palette, run "Forward a Port", and explicitly forward the HMR port. Second, browser extensions — especially aggressive ad blockers and CSP-rewriting extensions — sometimes drop WebSocket frames. Reproducing the issue in an Incognito window is the quickest way to rule this out. Third, with Vite specifically, pinning server.hmr.host and server.hmr.port in the config makes things dramatically more reliable across containers and remote sessions.

// vite.config.ts
import { defineConfig } from 'vite';
 
export default defineConfig({
  server: {
    host: '0.0.0.0',
    port: 5173,
    hmr: {
      // Make the WebSocket reachable across containers and proxies
      host: 'localhost',
      port: 5173,
      protocol: 'ws',
    },
  },
});
// Expected behavior: browser DevTools console shows
// "[vite] connected." right after the page loads.

Symptom B: The build never runs

If saving a file produces no log output at all, the file watcher isn't seeing your changes. This is the trickiest layer because the causes are diverse and often environment-specific.

The first suspect on Linux (including WSL and Devcontainers) is the inotify limit. Each watched file consumes one inotify slot, and large repositories blow through the default limit in seconds.

# Current limit
cat /proc/sys/fs/inotify/max_user_watches
# How many slots are currently in use
find /proc/*/fd -lname 'anon_inode:inotify' 2>/dev/null | wc -l
 
# Raise temporarily
sudo sysctl fs.inotify.max_user_watches=524288
# Persist across reboots
echo "fs.inotify.max_user_watches=524288" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

The misleading "No space left on device" error you sometimes see is actually inotify exhaustion. I've documented the full recovery path in How to Fix Antigravity File Watcher ENOSPC Errors, which is worth a read if you hit that specific message.

If inotify isn't the issue, the next thing to verify is whether the file you're editing is actually inside the watched set. Next.js and Vite both exclude node_modules, .next, and .git by default, but custom next.config.js rules — or editing through symlinks — can quietly leave your file outside the watcher's scope.

// next.config.js — explicitly broaden the watcher
module.exports = {
  webpack: (config, { dev }) => {
    if (dev) {
      // Follow symlinks; useful when monorepo packages are linked
      config.watchOptions = {
        followSymlinks: true,
        // Polling is the brute-force fallback; CPU-heavy but reliable
        poll: process.env.WATCH_POLL ? 1000 : false,
        ignored: ['**/node_modules/**', '**/.next/**'],
      };
    }
    return config;
  },
};
// To confirm: run WATCH_POLL=1 npm run dev. If CPU rises but
// HMR finally fires on save, the watcher itself was the issue.

Symptom C: Works at first, then dies

When HMR works for a while and then stops, it's almost always one of three things: a memory leak, an exhausted file watcher, or a dropped Antigravity session.

For memory, the OS-level tools are good enough — Activity Monitor on macOS, htop on Linux. If your node process climbs past 2 GB, you're entering the danger zone. Either start the dev server with NODE_OPTIONS=--max-old-space-size=4096, or build the habit of restarting it every couple of hours.

The Antigravity-specific failure mode here is interesting: when an AI agent commits a large batch of file edits, Antigravity's internal index can momentarily back up, which delays watcher notifications until it catches up. The fastest recovery I've found is running "Developer: Restart Extension Host" from the command palette — it's much lighter than restarting the whole editor and clears the backlog cleanly. If that doesn't help, your workspace index may be in worse shape; the recovery steps in Fixing a Stuck Antigravity Workspace Index cover the deeper cleanup.

A quick note on framework-specific quirks

Once you've ruled out the three big symptoms, a small number of framework-specific behaviors show up often enough to be worth knowing about.

With Next.js 14 and 16, App Router pages occasionally require a hard refresh after editing certain server components, because the server-side module graph and the client-side HMR boundary don't always agree on what changed. If a save updates the file but the page in the browser shows the old data, try a single Cmd-Shift-R (or Ctrl-Shift-R) to force a clean fetch — this isn't a bug in your setup, it's just how the boundary works for now.

With Vite, edits to files that are imported only by vite.config.ts won't trigger an HMR update because the config itself is loaded once at startup. Restart the dev server after changing build configuration; saving your config file alone will not produce visible behavior changes.

With Tailwind v3 and v4, missing class names sometimes look like an HMR failure when the real issue is the JIT scanner not picking up a newly added file path. Make sure your content (v3) or @source (v4) globs include any newly created directories.

These aren't bugs in Antigravity itself — they're framework-level edges that, when they line up with a separately broken piece of the stack, can make troubleshooting feel maddening. Knowing they exist helps you separate "my watcher is broken" from "my framework just doesn't reload this kind of edit."

Antigravity-specific gotchas

A few editor-specific things are easy to miss but routinely cause confusion.

First, Antigravity intentionally pauses parts of file-watching while an AI agent is mid-edit, to avoid spurious rebuilds during a large refactor. It resumes automatically when the agent finishes, but there's typically a brief window — a few seconds — when HMR feels broken. Wait, save again, and you'll usually find it's working.

Second, an overly broad files.watcherExclude in .antigravity/settings.json will silently exclude files you actually want to track. The fastest way to confirm this is to open "Toggle Developer Tools" in the editor and watch the console for save events; if no event fires when you save, the file is being filtered out.

Third, when you're using Antigravity's remote development extension, port forwarding is sometimes not persisted across restarts. Pinning remote.autoForwardPorts to true and listing your HMR port explicitly in remote.portsAttributes removes this whole class of problem.

A small ask before you go back to debugging

HMR breakage doesn't usually have a one-line fix — it has the classification I described above. Before you dive back in, the most useful thing you can do is write down whether you're seeing Symptom A, B, or C. That single decision prevents most of the time-sink that comes from randomly toggling settings.

Share

Thank You for Reading

Antigravity Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

App Dev2026-06-14
When the Edge Cache Pinned Next.js Error Pages: A cache-worker Guard Design
Users reported intermittent 'failed to load' errors I could never reproduce. The cause: SSR exceptions shipped as HTTP 200 and pinned by the edge cache. Here is how I narrowed it down with an Antigravity agent and added a cache-worker guard to stop it.
App Dev2026-05-03
Why `uv add transformers` Fails Inside Antigravity, and How to Actually Fix It
If `uv add transformers` errors out, or it succeeds but Antigravity's agent still throws ModuleNotFoundError, there are five distinct causes. Here is how to diagnose them in order.
App Dev2026-05-02
Stopping Server Action Foot-Guns Before Antigravity Ships Them — Zod, revalidate, and Authorization Built In From the First Draft
Ask Antigravity to write a Next.js Server Action and you'll often get back code with no Zod parsing, no revalidate call, and no authorization check. Here's how to bake those in from the start instead of patching them on later.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →