{"record":{"id":"b94d06f8a60484ba","repo":"jdx/mise","slug":"uv-project-at-has-an-empty-project-name","errorCode":null,"errorMessage":"uv project at {} has an empty project.name","messagePattern":"uv project at (.+?) has an empty project\\.name","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/task/workspace/uv.rs","lineNumber":125,"sourceCode":"        let mut known_roots = workspace_roots.clone();\n        let mut queue = workspace_roots.iter().cloned().collect::<VecDeque<_>>();\n        let mut manifests = BTreeMap::new();\n        while let Some(project_root) = queue.pop_front() {\n            if manifests.contains_key(&project_root) {\n                continue;\n            }\n            let relative = relative_root(&canonical_root, &project_root)?;\n            let pyproject_path = project_root.join(PYPROJECT_TOML);\n            let pyproject = if project_root == canonical_root {\n                root_pyproject.clone()\n            } else {\n                read_pyproject(context, &pyproject_path)?\n            };\n            let project = pyproject.project.as_ref().ok_or_else(|| {\n                eyre::eyre!(\"uv project at {} is missing [project]\", relative.display())\n            })?;\n            if project.name.is_empty() {\n                bail!(\n                    \"uv project at {} has an empty project.name\",\n                    relative.display()\n                );\n            }\n            let id = ProjectId::new(self.id(), &normalize_package_name(&project.name))?;\n            let workspace_member = workspace_roots.contains(&project_root);\n\n            for dependency in dependency_names(&pyproject) {\n                let Some((source, source_base)) = effective_source(\n                    &pyproject,\n                    &root_pyproject,\n                    &dependency,\n                    workspace_member,\n                    &project_root,\n                    &canonical_root,\n                ) else {\n                    continue;\n                };","sourceCodeStart":107,"sourceCodeEnd":143,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/task/workspace/uv.rs#L107-L143","documentation":"When discovering uv (Python) workspaces, mise reads pyproject.toml [project] tables and requires a non-empty project.name because the name becomes the workspace member's ProjectId. A [project] table with name = \"\" is invalid per uv/packaging rules, so mise refuses the project instead of producing a colliding or empty identifier.","triggerScenarios":"discover_with_context reads a pyproject.toml where [project] exists but project.name is an empty string.","commonSituations":"Scaffolded pyproject.toml with a placeholder empty name; a template that failed to substitute the project name; someone deleted the name value while editing.","solutions":["Set a valid project name in pyproject.toml: name = \"my-project\".","If the file is only a virtual/lock workspace config without a real project, remove the empty [project] table so it isn't treated as a project.","Re-run your project scaffolder to fill in the name placeholder."],"exampleFix":"# before\n[project]\nname = \"\"\n# after\n[project]\nname = \"my-project\"","handlingStrategy":"validation","validationCode":"import TOML from '@iarna/toml';\nconst doc = TOML.parse(readFileSync('pyproject.toml', 'utf8'));\nif (doc.project && (!doc.project.name || doc.project.name === '')) {\n  throw new Error('pyproject.toml [project] has empty name');\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never scaffold with name = \"\"; fill placeholders immediately.","Remove the [project] table from files that are not real Python projects."],"tags":["uv","python","workspace","pyproject"],"backgroundTag":"empty-required-field","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}