perspective-dev/perspective · error · Error

PKG-INFO value for field

Error message

PKG-INFO value for field ${name} was not a string:\n${value}

What it means

generatePkgInfo builds the wheel's PKG-INFO (core metadata spec 2.3) from pyproject.toml, Cargo.toml, and README.md. Its internal `field` helper throws when a metadata value is not a string, because a non-string cannot be rendered as a `Name: value` header line. This indicates a malformed or unexpectedly typed field (often a version read from Cargo.toml as a non-string, or a list/dict where a string was expected).

Solutions

  1. Inspect the pyproject.toml/Cargo.toml field named in the error and make sure its value is a quoted string (e.g. version = "1.2.3", not 1.2.3)
  2. Check generatePkgInfo's source assembly to see which source (pyproject, cargo, readme) supplies that field and fix the extraction if it yields a non-string
  3. Add a pre-build validation that all PKG-INFO fields are strings, or coerce/serialize lists explicitly before calling field()

Example fix

# before (pyproject.toml)
[project]
version = 1
// after
[project]
version = "1.0.0"
Defensive patterns

Strategy: validation

Validate before calling

const pyproject = require('./pyproject.toml');
for (const [k, v] of Object.entries(pyproject.project)) {
  if (typeof v === 'number' || typeof v === 'undefined') throw new Error(`Metadata field ${k} must be a string`);
}

Type guard

const isStr = (v) => typeof v === 'string';
if (!isStr(pyproject.project.version)) throw new Error('project.version must be a quoted string');

Try / catch

try { generatePkgInfo(pyproject, cargo, readme); } catch (e) { const m = e.message.match(/field (\w+) was not a string/); console.error(`Fix metadata field "${m?.[1]}" in pyproject.toml / Cargo.toml — it must be a string`); throw e; }

Prevention

When it happens

Trigger: Calling generatePkgInfo (via the build script) when any metadata field passed to `field(name, value)` is not typeof 'string' — e.g. pyproject `project.version` missing so a number/object is substituted, or a list field (like authors/classifiers) passed as a single-string field.

Common situations: Hand-edited pyproject.toml with a numeric version (e.g. version = 1.2 not "1.2"); Cargo.toml version parsed as a non-string; a required metadata field resolving to undefined/object after merging sources.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of perspective-dev/perspective@11c8238c0c (2026-09-09). Data as JSON: /api/errors/64a1311a5de83279. Report an issue: GitHub.

Appendix: source

Thrown at rust/perspective-python/build.mjs:184

if (process.env["PSP_UV"] === "1") {
    flags += " --uv";
}

if (!build_wheel && !build_sdist) {
    const dev_features = ["abi3"];
    execSync(
        `${emsdk_prefix}maturin develop --features=${dev_features.join(",")} ${flags} ${target}`,
        { stdio: "inherit", env },
    );
}

// Generates version 2.3 according to https://packaging.python.org/en/latest/specifications/core-metadata/
// Takes parsed pyproject.toml, Cargo.toml, and contents of README.md.
function generatePkgInfo(pyproject, cargo, readme_md) {
    const project = pyproject["project"];
    const field = (name, value) => {
        if (typeof value !== "string") {
            throw new Error(
                `PKG-INFO value for field ${name} was not a string:\n${value}`,
            );
        }
        return `${name}: ${value}`;
    };
    const lines = [];
    const addField = (key, value) => lines.push(field(key, value));
    addField("Metadata-Version", "2.3");
    addField("Name", project.name);
    addField("Version", cargo.package.version);
    for (const c of project["classifiers"]) {
        addField("Classifier", c);
    }
    for (const [extra, deps] of Object.entries(
        project["optional-dependencies"],
    )) {
        for (const dep of deps) {
            addField("Requires-Dist", `${dep} ; extra == '${extra}'`);

View on GitHub (pinned to 11c8238c0c)