{"record":{"id":"490565b964c17ac2","repo":"golang/go","slug":"parsing-go-mod-missing-module-line","errorCode":null,"errorMessage":"parsing go.mod: missing module line","messagePattern":"parsing go\\.mod: missing module line","errorType":"exception","errorClass":"module.VersionError","httpStatus":null,"severity":"error","filePath":"src/cmd/go/internal/modload/modfile.go","lineNumber":626,"sourceCode":"\t\t\tsuggestion := fmt.Sprintf(\" for go.mod file; to add it:\\n\\tgo mod download %s\", m.Path)\n\t\t\treturn nil, module.VersionError(actual, &sumMissingError{suggestion: suggestion})\n\t\t}\n\t}\n\tsummary, err := rawGoModSummary(ld, actual)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif actual.Version == \"\" {\n\t\t// The actual module is a filesystem-local replacement, for which we have\n\t\t// unfortunately not enforced any sort of invariants about module lines or\n\t\t// matching module paths. Anything goes.\n\t\t//\n\t\t// TODO(bcmills): Remove this special-case, update tests, and add a\n\t\t// release note.\n\t} else {\n\t\tif summary.module.Path == \"\" {\n\t\t\treturn nil, module.VersionError(actual, errors.New(\"parsing go.mod: missing module line\"))\n\t\t}\n\n\t\t// In theory we should only allow mpath to be unequal to m.Path here if the\n\t\t// version that we fetched lacks an explicit go.mod file: if the go.mod file\n\t\t// is explicit, then it should match exactly (to ensure that imports of other\n\t\t// packages within the module are interpreted correctly). Unfortunately, we\n\t\t// can't determine that information from the module proxy protocol: we'll have\n\t\t// to leave that validation for when we load actual packages from within the\n\t\t// module.\n\t\tif mpath := summary.module.Path; mpath != m.Path && mpath != actual.Path {\n\t\t\treturn nil, module.VersionError(actual,\n\t\t\t\tfmt.Errorf(\"parsing go.mod:\\n\"+\n\t\t\t\t\t\"\\tmodule declares its path as: %s\\n\"+\n\t\t\t\t\t\"\\t        but was required as: %s\", mpath, m.Path))\n\t\t}\n\t}\n\n\tfor _, mainModule := range ld.MainModules.Versions() {","sourceCodeStart":608,"sourceCodeEnd":644,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/cmd/go/internal/modload/modfile.go#L608-L644","documentation":"When the go command fetches and summarizes a module's go.mod, it expects a `module` declaration giving the module path. If that line is missing (summary.module.Path == \"\") and the module is NOT a local filesystem replacement (which are exempt), it returns this error wrapped in module.VersionError.","triggerScenarios":"A version of a module whose published go.mod lacks a `module` line, fetched from a proxy or VCS (actual.Version != \"\").","commonSituations":"Hand-edited or corrupt go.mod published by a dependency; ancient pre-modules code; proxy serving truncated content.","solutions":["Report the issue to the module maintainer to add a module line.","Select a different (correct) version of the module.","Replace the broken module with a fixed fork via a `replace` directive."],"exampleFix":"// before\n// upstream go.mod (broken): no `module` line\n$ go get example.com/lib@v1.0.0   // parsing go.mod: missing module line\n\n// after\n// replace example.com/lib v1.0.0 => github.com/you/lib-fork v1.0.1","handlingStrategy":"fallback","validationCode":"// Before depending on a module, fetch its go.mod summary and check for a module line.\nfunc hasModuleLine(modPath, version string) error {\n    return exec.Command(\"go\", \"mod\", \"download\", \"-json\", modPath+\"@\"+version).Run()\n}","typeGuard":"null","tryCatchPattern":"null","preventionTips":["Pin to known-good versions of third-party modules.","Use `replace` to redirect to a corrected fork when upstream is broken.","Verify modules with the checksum DB to detect corrupt content."],"tags":["go-mod","module-resolution","parsing","proxy"],"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T11:17:21.771Z"}