{"record":{"id":"c26d2df550f9fd25","repo":"dbt-labs/dbt-core","slug":"missing-project-name","errorCode":null,"errorMessage":"{}: missing `[project].name`","messagePattern":"(.+?): missing `\\[project\\]\\.name`","errorType":"validation","errorClass":"anyhow","httpStatus":null,"severity":"error","filePath":"crates/dbt-ci/src/pyproject.rs","lineNumber":78,"sourceCode":"    parse(dir)\n}\n\nfn parse(pyproject_dir: PathBuf) -> Result<Spec> {\n    let pp_path = pyproject_dir.join(\"pyproject.toml\");\n    let text = fs::read_to_string(&pp_path)\n        .with_context(|| format!(\"failed to read {}\", pp_path.display()))?;\n    let doc: DocumentMut = text\n        .parse()\n        .with_context(|| format!(\"failed to parse {}\", pp_path.display()))?;\n\n    let project = doc\n        .get(\"project\")\n        .ok_or_else(|| anyhow!(\"{}: missing `[project]` table\", pp_path.display()))?;\n\n    let wheel_name = project\n        .get(\"name\")\n        .and_then(|v| v.as_str())\n        .ok_or_else(|| anyhow!(\"{}: missing `[project].name`\", pp_path.display()))?\n        .to_string();\n\n    let summary = project\n        .get(\"description\")\n        .and_then(|v| v.as_str())\n        .map(str::to_string);\n\n    let requires_python = project\n        .get(\"requires-python\")\n        .and_then(|v| v.as_str())\n        .map(str::to_string);\n\n    let dependencies = string_array(project, \"dependencies\");\n    let classifiers = string_array(project, \"classifiers\");\n\n    let urls = project\n        .get(\"urls\")\n        .and_then(|t| t.as_table_like())","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/dbt-labs/dbt-core/blob/0267ce9170576975b76b64ce856b2e5848e96617/crates/dbt-ci/src/pyproject.rs#L60-L96","documentation":"This error is thrown while parsing a pyproject.toml during dbt CI: the `[project]` table exists but has no `name` key, or the value is not a string. The library requires a package name to derive the wheel name and downstream release metadata. It is a hard validation failure of the project metadata file.","triggerScenarios":"Running the CI parse path (discover/discover_at/parse) against a pyproject.toml whose `[project]` table omits `name` or defines `name` with a non-string value (e.g. a TOML table or integer).","commonSituations":"Hand-written pyproject.toml copied from old setuptools layouts without PEP 621 metadata; tool-specific configs that put the name under `[tool.poetry]` instead of `[project]`; a typo like `nmae = \"...\"`; or a generated file where a templating step dropped the name field.","solutions":["Add a string `name` field under the `[project]` table in pyproject.toml.","If using Poetry or another backend, also mirror the name into `[project].name` (PEP 621) or migrate to a backend that reads `[project]`.","Verify the file being parsed is the expected pyproject.toml (check the path shown in the error message).","Validate the TOML parses as expected with `tomlkit`/`tomllib` to rule out parse-level issues hiding the key."],"exampleFix":"# before (pyproject.toml)\n[project]\nversion = \"1.0.0\"\n\n// after\n[project]\nname = \"my-package\"\nversion = \"1.0.0\"","handlingStrategy":"validation","validationCode":"import tomllib\nwith open(\"pyproject.toml\", \"rb\") as f:\n    data = tomllib.load(f)\nassert isinstance(data.get(\"project\", {}).get(\"name\"), str), \"[project].name must be a string\"","typeGuard":"def has_project_name(doc: dict) -> bool:\n    name = doc.get(\"project\", {}).get(\"name\")\n    return isinstance(name, str) and bool(name)","tryCatchPattern":"try:\n    parse(pyproject_path)\nexcept anyhow::Error as e:\n    if \"missing `[project].name`\" in str(e):\n        fix_or_prompt_for_name(pyproject_path)\n    raise","preventionTips":["Keep PEP 621 [project].name present whenever you touch pyproject.toml","Run `changie`-style metadata lint or `python -m build --sdist` dry checks in CI to validate packaging metadata","Prefer template scaffolds that include name by default"],"tags":["config","toml","packaging","validation"],"backgroundTag":"missing-required-config-field","analyzedSha":"0267ce9170576975b76b64ce856b2e5848e96617","analyzedAt":"2026-09-07T21:53:39.732Z","contentChangedAt":"2026-09-07T21:53:39.732Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}