That tiny dopamine hit when ⌘S quietly straightens out your code is something you only notice when it stops happening. Prettier is installed. editor.formatOnSave is on. And yet the semicolons drift, indentation refuses to align, and worst of all — only your .tsx files get skipped while plain .ts formats fine.
I've stepped on every version of this trap while shipping with Antigravity. The good news: format-on-save almost never breaks for mysterious reasons. It breaks because one of three setting layers got overridden, and you can locate the culprit in about two minutes if you check them in the right order. That's exactly what this guide does, in priority order, with the assumption that you have ten minutes between meetings and you just want it working again.
The three settings to check first
Open Settings (⌘, or Ctrl+,) and search for format. Ninety-nine percent of broken format-on-save sessions trace back to one of these:
- Is
editor.formatOnSaveset totrue? - Is
editor.defaultFormatterpointing at a real, installed formatter (e.g.esbenp.prettier-vscode)? - For your specific language (e.g.
[typescript]), is the workspace overriding the default formatter to something else — or tonull?
The third one is the silent killer. Your global User settings might say "use Prettier," but a project-local .vscode/settings.json can override that for one repo only. Click the Workspace tab in the top-right of the Settings UI and verify nothing is being silently rewritten there. The Workspace tab is the single most useful piece of UI in this whole investigation, and most teammates I've worked with had never noticed it existed.
// .vscode/settings.json — the minimum config I commit on every project
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[javascriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}Commit that file and the "it works on my machine" version of this bug effectively disappears — every teammate ends up with the same formatter on save. If you only have time to do one thing from this article, do this one.
Picking the right formatter when several are installed
In the JS/TS world it's normal to have Prettier, ESLint, Biome, and Deno fmt all sitting in the extensions panel at the same time. Which one actually runs on save? Antigravity remembers the last formatter you explicitly chose, and that choice persists silently across sessions.
Open the Command Palette (⌘⇧P) and run Format Document With.... If a picker appears with multiple options, choose the one you actually want to use. From that moment on, format-on-save uses that selection. If your save action has been mysteriously calling the wrong formatter — say, the language's built-in JS/TS formatter instead of Prettier — this single click usually fixes it without touching any config files.
A common confusion worth spelling out: ESLint's --fix and Prettier's formatting are not the same thing. ESLint enforces code-quality rules and can rewrite a small subset of patterns. Prettier rewrites whitespace, quotes, semicolons, and line breaks based on a fixed style. If you want both to run on save, combine them via codeActionsOnSave:
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
"source.organizeImports": "explicit"
}
}Note the "explicit" value. Older guides still tell you to write true or false, but that legacy form is being deprecated. Antigravity follows the modern VS Code engine, so future-proof your config by switching now. Adding source.organizeImports is also a small quality-of-life upgrade — saves you from manually sorting imports later.
When a single file extension misbehaves
"My .ts files format fine, but .tsx is ignored." "Only Markdown gets skipped." Symptoms like these almost always point to a per-language override. In Settings, type the language ID (typescriptreact, markdown) into the search box and inspect editor.defaultFormatter. An empty value or a stale extension ID is your culprit.
It's also worth checking whether the formatter itself excludes that file type. For Prettier, scan .prettierignore for unexpected entries, and look at prettier.config.js for overrides that might silently exempt a glob.
// prettier.config.js — make sure overrides aren't quietly excluding files
module.exports = {
semi: true,
singleQuote: true,
overrides: [
{
files: "*.md",
options: { proseWrap: "preserve" }
}
]
};I once spent an hour debugging "my teammate's .tsx files won't format" only to discover an old *.tsx line still living in .prettierignore from a hot fix two years prior. Five seconds of git log -p .prettierignore would have shown me the answer immediately. Make this part of your debugging muscle memory: when an ignore-style file is suspect, read the diff history before guessing.
One Antigravity-specific gotcha: if you opened the file via "Open Recent" with a stale workspace path that no longer matches the actual repo on disk, .prettierignore and prettier.config.js may resolve from an unexpected location. Confirm that the editor title bar shows the same workspace folder you'd expect.
When extensions fight each other (and the AI joins in)
A newer flavor of this bug: AI completion or linter-style extensions quietly run their own transformation after Prettier, overwriting the result. Open the Output panel (⌘⇧U), switch the channel to Prettier, then ESLint, then your AI extension — you'll see exactly which extension fired on save and in what order.
If multiple formatters are running, revisit codeActionsOnSave. The most reliable order is "linter fixAll → Prettier formatter." Reversing it lets each extension overwrite the other, which is the recipe for non-deterministic save behavior. The reason this matters is subtle but important: ESLint's --fix may rearrange code in a way that triggers different Prettier output than you'd see if you formatted first, so deciding the order intentionally is part of writing a stable config.
There's also a subtle interaction: AI completion sometimes shifts the cursor at the moment you save, and that shift can cancel format-on-save mid-flight. If you suspect this, temporarily disable the AI extension and confirm formatting alone behaves. If it does, you've found the conflict — and the workaround is usually to delay the AI completion's auto-confirm or disable its on-save hook.
If your AI extension exposes a "format on apply" or "fix on insert" toggle, that's typically the lever to flip. Two formatters fighting on save is one of those bugs that's invisible to git diff because the file ends up in some plausible-but-wrong intermediate state.
Quick verification: how to tell which formatter actually ran
Before you blow up your config, confirm what actually fires on save. Open a deliberately ugly throwaway file (mismatched quotes, random whitespace), watch the Output panel as you save, and note the order of log lines. If Prettier logs Formatting ... and the file changes — your pipeline is fine and the issue is config drift on a specific repo. If Prettier never logs anything, format-on-save isn't reaching it at all. This 30-second test is the difference between "my settings are wrong" and "my settings are right but ignored," and the fixes for those two cases are completely different. I run this test reflexively now, before I touch a single config file, because it saves me from chasing the wrong layer of the problem entirely.
Last-resort recovery checklist
Still broken? Antigravity's settings cache may be corrupted. Work through these in order:
- Run
Developer: Reload Windowfrom the Command Palette — this is the cheapest possible fix and resolves a surprising number of "everything stopped working" bugs - Comment out the format-related lines in your user
settings.json, reload, then add them back one line at a time. The line that breaks formatting on its own is the one to investigate - In the Extensions view, disable and re-enable your formatter extension to force a fresh load
- Check
Output → Log (Extension Host)for thrown errors. Format-on-save failures often surface there as silent stack traces that never bubble up to a notification
A single habit that prevents future Format on Save outages
Most format-on-save failures come down to not knowing which override layer is doing the overriding. The habit I now follow on every new project: in the very first commit, drop in .vscode/settings.json, .prettierrc, and .editorconfig together. Adding them later is when you stumble into "it works on my machine, but not on theirs."
If you're chasing other editor bugs, pair this article with Antigravity tab completion not working, Antigravity language server (LSP) not responding, and Antigravity Settings Sync not working. Together they cover the most common editor-layer breakage patterns you'll hit in your first month with Antigravity.
The single concrete step worth doing today: open .vscode/settings.json in your current project and confirm editor.defaultFormatter is set to the same value your team uses. That one line removes about half of "format-on-save mysteriously broke" days from your future.