Hmbown/CodeWhale · error · ValueError

ProvidersToml returned no provider tables

Error message

ProvidersToml returned no provider tables

What it means

provider_tables extracted the `pub struct ProvidersToml` block from crates/config/src/lib.rs but found no `pub <field>: ProviderConfigToml` members inside it. Those fields define the set of `[providers.*]` TOML tables the docs-drift check compares against, so an empty or reshaped struct cannot be validated. Field types other than exactly ProviderConfigToml are invisible to the regex.

Source

Thrown at scripts/check-provider-registry.py:196

    variant_to_id = provider_kind_ids("")
    # ApiProvider::SiliconflowCn maps to ProviderKind::SiliconflowCN
    if "SiliconflowCN" in variant_to_id:
        variant_to_id["SiliconflowCn"] = variant_to_id["SiliconflowCN"]
    variant_to_id["DeepseekCN"] = "deepseek-cn"
    return variant_to_id


def provider_tables(config_rs: str) -> set[str]:
    struct_start = require_index(
        config_rs, "pub struct ProvidersToml", "crates/config/src/lib.rs"
    )
    struct_end = require_index(config_rs, "\n}", "ProvidersToml struct", struct_start)
    fields = re.findall(
        r"pub\s+([a-z0-9_]+)\s*:\s*ProviderConfigToml",
        config_rs[struct_start:struct_end],
    )
    if not fields:
        raise ValueError("ProvidersToml returned no provider tables")
    return set(fields)


def shipped_provider_rows(providers_md: str) -> set[str]:
    table = markdown_section(providers_md, "## Shipped Providers")
    return set(re.findall(r"^\|\s*`([^`]+)`\s*\|", table, flags=re.MULTILINE))


def shipped_provider_tables(providers_md: str) -> set[str]:
    table = markdown_section(providers_md, "## Shipped Providers")
    return set(re.findall(r"\|\s*`\[providers\.([a-z0-9_]+)\]`\s*\|", table))


def static_registry_provider_rows(providers_md: str) -> set[str]:
    table = markdown_section(providers_md, "## Static Model Registry")
    return set(re.findall(r"^\|\s*`([^`]+)`\s*\|", table, flags=re.MULTILINE))

View on GitHub (pinned to 8880682c63)

Solutions

  1. Keep ProvidersToml fields shaped as `pub <name>: ProviderConfigToml`
  2. If the field type was renamed, update the regex in provider_tables() to the new type name
  3. If the struct moved, update the CONFIG_RS path constant or the struct anchor string in the script

Example fix

// before
pub struct ProvidersToml {
    pub deepseek: Option<ProviderConfigToml>,
}
// after
pub struct ProvidersToml {
    pub deepseek: ProviderConfigToml,
}
Defensive patterns

Strategy: try-catch

Validate before calling

fields = re.findall(r'pub\s+([a-z0-9_]+)\s*:\s*ProviderConfigToml', config_rs)
assert fields, 'ProvidersToml shape changed — update the checker'

Try / catch

try:
    tables = provider_tables(config_rs)
except ValueError as e:
    inspect_struct_providers_toml(); raise

Prevention

When it happens

Trigger: Changing field types to Option<ProviderConfigToml> or a renamed config type; replacing the struct's fields with a serde(flatten) HashMap; deleting all provider fields; renaming ProviderConfigToml itself.

Common situations: Making per-table provider config optional; centralizing config into a map; type renames during config-crate refactors.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16). Data as JSON: /api/errors/1fb722c8411df4e7. Report an issue: GitHub.