astrid-runtime/astrid · error

signed Distro.toml has no [distro.signing] configuration

Error message

signed Distro.toml has no [distro.signing] configuration

What it means

verify_signed_manifest requires the parsed Distro.toml to carry a `[distro.signing]` table (containing the pubkey) before it can verify the Ed25519 signature over the lock. If `manifest.distro.signing` is None the manifest cannot be authenticated, so the CLI refuses to proceed.

Solutions

  1. Add a `[distro.signing]` table with a `pubkey` field to the published Distro.toml (generate via `astrid keypair generate` and convert with the ed25519:<base64> wire form)
  2. Confirm the source actually points at the signed manifest, not an older unsigned one
  3. Re-check TOML section spelling and that the file parses with `signing` under `distro`

Example fix

# before
[distro]
id = "my-distro"
# after
[distro]
id = "my-distro"
[distro.signing]
pubkey = "ed25519:<base64-public-key>"
Defensive patterns

Strategy: validation

Validate before calling

let toml = std::fs::read_to_string("Distro.toml")?;
let manifest: DistroManifest = toml::from_str(&toml)?;
if manifest.distro.signing.is_none() {
    anyhow::bail!("Distro.toml is missing [distro.signing]; add it before sealing/publishing");
}

Type guard

fn has_signing(m: &DistroManifest) -> bool { m.distro.signing.is_some() }

Try / catch

match verify_signed_manifest(/*..*/).await {
    Err(e) if e.to_string().contains("no [distro.signing]") => {
        eprintln!("Published Distro.toml lacks [distro.signing]; regenerate a signed manifest");
    }
    r => r?,
}

Prevention

When it happens

Trigger: fetch_signed_manifest verifies a signed Distro.toml whose `[distro.signing]` section is missing — typically because the signing table was removed, the wrong (unsigned/legacy) Distro.toml is deployed at the source, or the table name is misspelled.

Common situations: Upgrading an old distro layout to signed sources without adding `[distro.signing]`; copying a Distro.toml template that omits the signing block; a `signings`/`signing` typo in TOML.

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 astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/d296121cd08f619f. Report an issue: GitHub.

Appendix: source

Thrown at crates/astrid-cli/src/commands/init_signed_source.rs:302

}

/// Bind exact TOML bytes into the signed lock, then verify that lock.
fn verify_signed_manifest(
    home: &AstridHome,
    manifest: &DistroManifest,
    manifest_hash: &str,
    lock: &DistroLock,
    sig_hex: &str,
    accept_new_key: bool,
) -> anyhow::Result<HashMap<String, String>> {
    if lock.manifest_hash.as_deref() != Some(manifest_hash) {
        bail!(
            "signed Distro.toml does not match Distro.lock manifest_hash; refusing to resolve members"
        );
    }
    validate_signed_member_sets(manifest, lock)?;
    let signing = manifest.distro.signing.as_ref().ok_or_else(|| {
        anyhow::anyhow!("signed Distro.toml has no [distro.signing] configuration")
    })?;
    let outcome = trust::verify_and_pin(
        home,
        &manifest.distro.id,
        &signing.pubkey,
        sig_hex,
        lock,
        accept_new_key,
        trust::TrustPolicy::RequireExistingPin,
    )?;
    tracing::info!(
        distro = %manifest.distro.id,
        action = ?outcome.action,
        "authenticated source Distro"
    );

    Ok(lock
        .capsules

View on GitHub (pinned to affd8760f4)