go mod vendor — Specification¶
Table of Contents¶
- Introduction
- Where
go mod vendorIs Specified - Synopsis
- What Vendor Does (Per the Reference Text)
- The
-e,-v,-oFlags - The
vendor/modules.txtFile: Specified Format - Vendor Auto-Detection Rules (Go 1.14+)
- The
-mod=vendorand-mod=modFlags (andGOFLAGS) - What Is and Is NOT Vendored (Per Reference)
- Vendor and
replaceDirectives - Vendor Consistency Errors
- Differences Across Go Versions
- References
Introduction¶
The Go language specification (go.dev/ref/spec) does not specify go mod vendor. The command is part of the tooling, not the language. The authoritative reference is the Go Modules Reference at go.dev/ref/mod, supplemented by the toolchain source.
Sources of truth, in decreasing formality:
- Go Modules Reference —
go.dev/ref/mod, in particular the "Vendoring" and "go mod vendor" sections. go help mod vendor— terse, command-line oriented.- Toolchain source —
cmd/go/internal/modcmd/vendor.go(the command driver) andcmd/go/internal/modload/vendor.go(the consistency checker for build-time use).
This file separates "what the modules reference says" from convention and tooling implementation. Where the reference is silent, the toolchain source is the de-facto specification.
Where go mod vendor Is Specified¶
go mod vendor is documented in three places officially:
go help mod vendor— the help text.- Go Modules Reference, Section "
go mod vendor" — detailed prose. - Go Modules Reference, Section "Vendoring" — describes the build-time consumption rules.
A paraphrase of go help mod vendor (paraphrased; consult go help mod vendor for the exact current text):
go mod vendorresets the main module'svendor/directory to contain all packages needed to build and test packages of the main module. Packages of the standard library and packages from modules in the workspace are excluded. With-v, the names of vendored modules and packages are printed to standard error. With-e, errors that occur while loading packages are reported but do not stop the command. With-o, the vendor directory is written to the named output directory; note that vendor consumption by thegobuild tool only honours the standardvendor/location.
That paraphrase is the substance; the reference page expands on every clause.
Synopsis¶
- All flags are optional.
- The command operates on the main module (the module containing the current directory). It refuses to run if there is no
go.mod. - Exit code 0 on success, non-zero on I/O error or (when
-eis not set) on a package-loading error. - Output:
- A
vendor/directory at the module root (oroutdirif-ois set). - A
vendor/modules.txtfile with the format described in section 6. - With
-v, a list of vendored modules and packages on stderr.
What Vendor Does (Per the Reference Text)¶
The Go Modules Reference describes the operation as follows (paraphrased):
- The main module is loaded from
go.mod. - The set of build-time and test-time package imports of the main module is computed for the default build list — the set of platforms relevant to the current
GOOS/GOARCHplus those reachable through the main module's package graph. - For each imported package outside the standard library and outside the main module, the toolchain copies the source files needed for the build into
vendor/<import-path>/. - A
vendor/modules.txtfile is generated, recording (a) every module that contributed packages, (b) the list of packages drawn from each module, and (c) markers describing the role of each module. - The previous contents of
vendor/(if any) are removed.
The reference is explicit on three properties:
- The operation is deterministic: the same module graph and
go.modproduce the samevendor/tree. - The operation is idempotent: running it twice in succession leaves no diff on the second run.
- The operation does not modify
go.modorgo.sum.
The -e, -v, -o Flags¶
| Flag | Reference behaviour | Added in |
|---|---|---|
-e | Continue on errors that occur while loading packages. The exit code is still non-zero if any error was encountered, but the partial vendor/ is still written. | Go 1.16 |
-v | Verbose. Names of vendored modules and packages are printed to standard error, one per line. | Go 1.11 (initial) |
-o outdir | Write the vendor directory to outdir instead of <module>/vendor. The outdir is created if absent and reset if present. Important: the build tool's auto-detection of vendor/ (section 7) still requires the standard <module>/vendor location; an -o-produced tree is not consulted by builds unless renamed. | Go 1.18 |
The reference notes that -o is intended for inspection, packaging, and CI artifacts — not as a substitute for the on-disk vendor/ location at the module root.
The vendor/modules.txt File: Specified Format¶
The Go Modules Reference defines the format of vendor/modules.txt. The grammar (paraphrased; informal):
modulesTxt = { ModuleBlock } .
ModuleBlock = ModuleHeader { Marker } { PackageLine } .
ModuleHeader = "# " ModulePath " " Version
| "# " ModulePath " " Version " => " TargetPath " " TargetVersion
| "# " ModulePath " => " TargetPath
.
Marker = "## explicit"
| "## explicit; go " GoVersion
| "## go " GoVersion
.
PackageLine = PackageImportPath "\n" .
Concretely:
- A module header begins with
#and names a module and its selected version. If the module is the target of areplacedirective, the=>form is used and both sides are recorded. - The
## explicitmarker indicates the module is a direct dependency (it appears in arequiredirective of the main module'sgo.mod). Without this marker, the module is an indirect dependency. - The
## explicit; go <version>marker (Go 1.17+) records the dependency module's owngodirective value, which the toolchain uses for language-version-dependent semantics during compilation. - Package lines list the import paths of packages from this module that are needed by the build. One per line, no leading
#.
The file is consumed by the build tool to (a) verify consistency with go.mod and (b) restrict the set of packages available from each vendored module.
Vendor Auto-Detection Rules (Go 1.14+)¶
Per the Go Modules Reference, the go build tool defaults to -mod=vendor when all of the following hold:
- The current directory is inside a module (a
go.modis found upward). - A
vendor/modules.txtfile exists at the module root. - The
godirective ingo.modis1.14or higher.
If any condition fails, the default is -mod=readonly (Go 1.16+) or -mod=mod (older). The auto-detection check happens before each invocation of go build, go test, go run, go install, etc.
A vendor/ directory without a modules.txt file is treated as if vendoring were not enabled — older-style vendor/ directories from pre-modules tooling will not trigger auto-detection.
A go.mod with a go directive lower than 1.14 will not auto-enable vendoring even if vendor/modules.txt is present; the user must opt in with -mod=vendor.
The -mod=vendor and -mod=mod Flags (and GOFLAGS)¶
The -mod flag controls how the go command resolves dependencies. Specified values:
| Value | Meaning |
|---|---|
mod | Fetch missing modules from the network/module cache. May modify go.mod and go.sum. |
readonly | Use go.mod as-is; fail if any module is missing or requires a change. (Default outside vendor mode since Go 1.16.) |
vendor | Use the vendor/ tree exclusively. Network access is disabled for module resolution. The vendor/modules.txt file must agree with go.mod (section 11). |
The flag may be set:
- On the command line:
go build -mod=vendor ./... - Via the environment variable
GOFLAGS:GOFLAGS='-mod=vendor' - Implicitly by auto-detection (section 7).
In vendor mode, the go command does not consult the module cache or any network proxy for the modules listed in modules.txt.
What Is and Is NOT Vendored (Per Reference)¶
Included by go mod vendor:
- All non-test
.gosource files of every package imported, transitively, by the main module's packages and tests. - Test files (
_test.go) of packages of the main module — but not of dependencies. - Embedded files (
//go:embedtargets) of vendored packages. LICENSE,LICENSE.txt,LICENCE,COPYING,PATENTS, andNOTICEfiles at the module root and at each package directory of vendored modules (these are copied verbatim).
Excluded by go mod vendor:
_test.gofiles of dependency packages — the reference is explicit that dependency tests are not vendored.- Files inside
testdata/directories of dependency packages. - Files outside the build graph for any combination of
GOOS/GOARCHreached from the main module — purely platform-specific files for unreachable platforms are skipped. - Documentation-only files (
.md,README, etc.) — except the legal files listed above. - The
vendor/directories of vendored modules themselves (no nesting). - Source files of the standard library.
- Source files of modules within the same workspace (
go.work-mode only).
The exclusion rule for tests has practical consequence: a vendored module cannot be re-tested in isolation from its vendored copy.
Vendor and replace Directives¶
The replace directive in go.mod redirects a module path to another path or to a local directory. go mod vendor honours replace as follows:
- The content copied into
vendor/<module-path>/comes from the replacement target (the right-hand side of=>). - The directory name under
vendor/is the original module path (the left-hand side of=>). - The
vendor/modules.txtmodule header records both:# orig.path v1.0.0 => target.path v1.0.0(or=> ../local/dir).
Local-directory replacements (replacements whose right-hand side is a filesystem path) are also copied — the local directory is treated as a module and its packages are vendored normally. The relative path is preserved in modules.txt for diagnostic purposes.
Replacement of the main module is not meaningful in vendor mode.
Vendor Consistency Errors¶
Per the Go Modules Reference, vendor mode requires that vendor/modules.txt agree with go.mod. Specifically:
- Every module required by
go.mod(transitively, via the module graph asgo.modrecords it) must appear inmodules.txtwith the same selected version. - Every module marked
## explicitinmodules.txtmust appear in arequiredirective ofgo.mod. - The
## explicit; go <version>markers (Go 1.17+) must match thegodirective of the corresponding dependency'sgo.modas recorded. - Replacement entries must agree: a
replaceingo.modmust produce a=>line inmodules.txt, and vice versa.
A mismatch is an error. The error message names the offending module and recommends go mod vendor to regenerate. The build does not proceed.
The reference frames this strictness as a deliberate guarantee: in vendor mode, the source of truth is the vendor/ tree, but it must be exactly the tree that go.mod describes.
Differences Across Go Versions¶
The behaviour of go mod vendor has evolved:
- Go 1.11 —
go mod vendorintroduced.-mod=vendorexists as an opt-in flag; vendoring is not auto-detected. - Go 1.12 — Bug fixes to
modules.txtformatting; no behavioural change. - Go 1.13 — Module proxy and sum DB introduced (downstream).
- Go 1.14 —
vendor/becomes auto-detected: builds in a module withvendor/modules.txtandgo >= 1.14use vendor mode by default. - Go 1.16 —
-eflag added (continue on errors).-mod=readonlybecomes the default outside vendor mode. - Go 1.17 —
## explicit; go <version>markers added tomodules.txt. The dependency'sgodirective is recorded. - Go 1.18 —
-o outdirflag added. Workspaces (go.work) introduced; vendoring is per-module, not per-workspace. - Go 1.21 —
toolchaindirective interaction documented;modules.txtunaffected. - Go 1.22 —
go work vendoradded as a separate command for workspace-level vendoring;go mod vendoritself is unchanged. - Go 1.23 — Minor improvements to error messages on consistency mismatch.
The mechanical command — go mod vendor writes a vendor/ tree and vendor/modules.txt — has remained stable since Go 1.11. The auto-detection and the marker format have been the principal additions.