dbt-labs/dbt-core · error · anyhow

{}: missing `[project].name`

Error message

{}: missing `[project].name`

What it means

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.

Source

Thrown at crates/dbt-ci/src/pyproject.rs:78

    parse(dir)
}

fn parse(pyproject_dir: PathBuf) -> Result<Spec> {
    let pp_path = pyproject_dir.join("pyproject.toml");
    let text = fs::read_to_string(&pp_path)
        .with_context(|| format!("failed to read {}", pp_path.display()))?;
    let doc: DocumentMut = text
        .parse()
        .with_context(|| format!("failed to parse {}", pp_path.display()))?;

    let project = doc
        .get("project")
        .ok_or_else(|| anyhow!("{}: missing `[project]` table", pp_path.display()))?;

    let wheel_name = project
        .get("name")
        .and_then(|v| v.as_str())
        .ok_or_else(|| anyhow!("{}: missing `[project].name`", pp_path.display()))?
        .to_string();

    let summary = project
        .get("description")
        .and_then(|v| v.as_str())
        .map(str::to_string);

    let requires_python = project
        .get("requires-python")
        .and_then(|v| v.as_str())
        .map(str::to_string);

    let dependencies = string_array(project, "dependencies");
    let classifiers = string_array(project, "classifiers");

    let urls = project
        .get("urls")
        .and_then(|t| t.as_table_like())

View on GitHub (pinned to 0267ce9170)

Solutions

  1. Add a string `name` field under the `[project]` table in pyproject.toml.
  2. If using Poetry or another backend, also mirror the name into `[project].name` (PEP 621) or migrate to a backend that reads `[project]`.
  3. Verify the file being parsed is the expected pyproject.toml (check the path shown in the error message).
  4. Validate the TOML parses as expected with `tomlkit`/`tomllib` to rule out parse-level issues hiding the key.

Example fix

# before (pyproject.toml)
[project]
version = "1.0.0"

// after
[project]
name = "my-package"
version = "1.0.0"
Defensive patterns

Strategy: validation

Validate before calling

import tomllib
with open("pyproject.toml", "rb") as f:
    data = tomllib.load(f)
assert isinstance(data.get("project", {}).get("name"), str), "[project].name must be a string"

Type guard

def has_project_name(doc: dict) -> bool:
    name = doc.get("project", {}).get("name")
    return isinstance(name, str) and bool(name)

Try / catch

try:
    parse(pyproject_path)
except anyhow::Error as e:
    if "missing `[project].name`" in str(e):
        fix_or_prompt_for_name(pyproject_path)
    raise

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07). Data as JSON: /api/errors/c26d2df550f9fd25. Report an issue: GitHub.