The manifest
[overrides]
Last updated August 24, 2026
[overrides] replaces a dependency of a dependency — when a package
you depend on pulls a version you don't want, or you would rather it used
your fork:
[dependencies]
Comm = { name = "sleitnick/comm", version = "^1", index = "wally" }
Signal = { name = "sleitnick/signal", version = "=2.0.0", index = "wally" }
[overrides]
"Comm.Signal" = "Signal"
That reads: wherever Comm asks for its Signal, use mine instead —
including when yours is a fork under a completely different package name.
(Coming from pesde? Same idea; Ember writes . where pesde writes >.)
Keys are alias paths#
Dot-separated, at least two segments:
- The first segment is an alias under your
[dependencies]. - Each further segment is the alias the previous package's own manifest
declares for its dependency — case-sensitive, spelled exactly as that
package wrote it. Wally packages usually capitalize:
Promise, notpromise. - Segments are aliases, never package names.
- One key can cover several paths, separated by commas:
"Foo.Bar, Baz.Bar" = …. - Aliases containing dots or whitespace cannot be addressed.
Values#
Both shapes work, alias shorthand and full specifier:
[overrides]
# Alias shorthand: one of your own [dependencies] entries.
"Comm.Signal" = "Signal"
# Full specifiers: the same shapes a [dependencies] value takes.
"Comm.Promise" = { name = "evaera/promise", version = "^4", index = "wally" }
"Comm.Util" = { workspace = "acme/util" }
- An alias string — the alias of one of your own
[dependencies]entries. The replacement can be a fork under a completely different package name; the alias is what matters. - A full specifier — registry
(
{ name = …, version = …, index = … }) or workspace ({ workspace = … }), exactly like[dependencies]values. Anindexkey resolves against your[indices], not the overridden package's.
What an override actually changes#
Ember installs one version per package name per environment root, and an override redirects one edge. Dependents that ask for the original package by name keep it, so the original and the replacement then coexist in that root, each linked where it was asked for.
A package's dependency edges are considered once, on first discovery
(your [dependencies] aliases seed in alphabetical order). A deeper path
like "A.B.C" has to spell that first route; if the package at A.B was
first reached some other way, Ember warns and names the route that was
walked. Segments below an overridden edge address the replacement's
dependencies.
Overrides don't suspend version checking — if an override's requirement conflicts with what another dependent demands of the same package, install fails with the normal dependency conflict error.
The lockfile records redirected edges, so --locked reproduces them
exactly. Only the installing project's [overrides] applies — a
dependency's own table never reshapes your install (published packages
don't carry one; publish strips the table), and in a
workspace a member's own table applies when that
member installs.
Diagnostics#
Checked at install, before any network traffic. Errors:
[overrides] key '<key>' must be a dot-separated path like 'parent.child' (commas separate multiple paths)Override '<path>' points at '<alias>', which is not under [dependencies]Two [overrides] keys both cover the path '<path>'- an unknown
indexkey in a value fails like any dependency's would
Warnings, which install continues past:
warning: override '<path>' matched no dependency; check the alias pathwarning: override '<path>' could not apply: that package's dependencies were walked via '<other path>' first; address the edge there