{"record":{"id":"5116ce5180488edc","repo":"jdx/mise","slug":"go-workspace-module-is-missing-go-mod","errorCode":null,"errorMessage":"Go workspace module {} is missing {GO_MOD}","messagePattern":"Go workspace module (.+?) is missing (.+?)","errorType":"validation","errorClass":"eyre::Report","httpStatus":null,"severity":"error","filePath":"src/task/workspace/go.rs","lineNumber":63,"sourceCode":"\n        for directory in module_directories {\n            let candidate = if directory.is_absolute() {\n                directory\n            } else {\n                workspace_root.join(directory)\n            };\n            let lexical_candidate = lexical_absolute(&candidate)?;\n            if !lexical_candidate.starts_with(&lexical_root)\n                && !lexical_candidate.starts_with(&canonical_root)\n            {\n                continue;\n            }\n            let candidate = lexical_candidate;\n            if !context.exists(&candidate) {\n                if missing_path_resolves_outside(&candidate, &lexical_root, &canonical_root)? {\n                    continue;\n                }\n                bail!(\n                    \"Go workspace module {} is missing {GO_MOD}\",\n                    candidate.display()\n                );\n            }\n            let canonical_module = context.canonicalize(&candidate).wrap_err_with(|| {\n                format!(\n                    \"failed to resolve Go workspace module {}\",\n                    candidate.display()\n                )\n            })?;\n            let Ok(relative) = canonical_module.strip_prefix(&canonical_root) else {\n                continue;\n            };\n            if !context.is_file(&canonical_module.join(GO_MOD)) {\n                bail!(\n                    \"Go workspace module {} is missing {GO_MOD}\",\n                    candidate.display()\n                );","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/jdx/mise/blob/6f52dcdf99e282ef7a7db68c81301fa4618d0f79/src/task/workspace/go.rs#L45-L81","documentation":"Raised by the Go workspace provider when a directory listed in go.work's use directives does not exist on disk (context.exists fails and the missing path does not resolve outside the workspace via symlink logic). The message points at the expected go.mod because every use entry must be a module directory containing one.","triggerScenarios":"go.work contains use ./svc/auth but svc/auth was deleted or renamed without running `go work edit -dropuse`; a stale go.work after moving a module; sparse/partial checkouts where the listed directory was not fetched.","commonSituations":"Deleting or moving a module directory and forgetting go.work; merging branches that move modules; CI with sparse checkout; manually trimming directories to speed builds.","solutions":["Drop the stale entry: `go work edit -dropuse ./svc/auth` (or edit go.work by hand)","Restore or recreate the directory with `go mod init` if the module should still exist","Regenerate the file with `go work use ./...` from the workspace root to rebuild an accurate use list"],"exampleFix":"# before (go.work)\ngo 1.23\n\nuse (\n    ./api\n    ./deleted-svc\n)\n\n# after\ngo 1.23\n\nuse (\n    ./api\n)","handlingStrategy":"validation","validationCode":"let go_work = std::fs::read_to_string(\"go.work\")?;\nfor line in go_work.lines() {\n    let line = line.split(\"//\").next().unwrap_or(\"\").trim();\n    if let Some(arg) = line.strip_prefix(\"use \") {\n        for dir in arg.trim_matches(|c| c == '(' || c == ')').split_whitespace() {\n            let dir = dir.trim_matches('\"');\n            if !std::path::Path::new(dir).exists() {\n                return Err(eyre::eyre!(\"go.work lists missing directory {dir}\"));\n            }\n        }\n    }\n}","typeGuard":"fn go_work_use_dirs_exist(root: &Path) -> bool {\n    let Ok(contents) = std::fs::read_to_string(root.join(\"go.work\")) else { return true; };\n    let mut in_block = false;\n    for raw in contents.lines() {\n        let line = raw.split(\"//\").next().unwrap_or(\"\").trim();\n        let arg = if in_block { line } else { line.strip_prefix(\"use \").map(str::trim).unwrap_or(\"\") };\n        if arg == \"(\" { in_block = true; continue; }\n        if in_block && line == \")\" { in_block = false; continue; }\n        if !arg.is_empty() && !root.join(arg.trim_matches('\"')).exists() { return false; }\n    }\n    true\n}","tryCatchPattern":"Err(report) if report.to_string().contains(\"is missing go.mod\") => {\n    // run the toolchain's own repair: `go work edit -dropuse <dir>`, then retry discovery\n    std::process::Command::new(\"go\").args([\"work\", \"edit\", \"-dropuse\", dir]).status();\n}","preventionTips":["After deleting or moving a module, immediately run `go work edit -dropuse ./old` or `go work use ./...`","Run `go work sync` in CI to catch stale use entries early","Treat go.work like a lockfile in code review: update it in the same commit as directory moves"],"tags":["go","workspace","go-work","missing-file","discovery"],"backgroundTag":"missing-manifest-file","analyzedSha":"6f52dcdf99e282ef7a7db68c81301fa4618d0f79","analyzedAt":"2026-08-22T10:14:23.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}