{"record":{"id":"1fb722c8411df4e7","repo":"Hmbown/CodeWhale","slug":"providerstoml-returned-no-provider-tables","errorCode":null,"errorMessage":"ProvidersToml returned no provider tables","messagePattern":"ProvidersToml returned no provider tables","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"scripts/check-provider-registry.py","lineNumber":196,"sourceCode":"    variant_to_id = provider_kind_ids(\"\")\n    # ApiProvider::SiliconflowCn maps to ProviderKind::SiliconflowCN\n    if \"SiliconflowCN\" in variant_to_id:\n        variant_to_id[\"SiliconflowCn\"] = variant_to_id[\"SiliconflowCN\"]\n    variant_to_id[\"DeepseekCN\"] = \"deepseek-cn\"\n    return variant_to_id\n\n\ndef provider_tables(config_rs: str) -> set[str]:\n    struct_start = require_index(\n        config_rs, \"pub struct ProvidersToml\", \"crates/config/src/lib.rs\"\n    )\n    struct_end = require_index(config_rs, \"\\n}\", \"ProvidersToml struct\", struct_start)\n    fields = re.findall(\n        r\"pub\\s+([a-z0-9_]+)\\s*:\\s*ProviderConfigToml\",\n        config_rs[struct_start:struct_end],\n    )\n    if not fields:\n        raise ValueError(\"ProvidersToml returned no provider tables\")\n    return set(fields)\n\n\ndef shipped_provider_rows(providers_md: str) -> set[str]:\n    table = markdown_section(providers_md, \"## Shipped Providers\")\n    return set(re.findall(r\"^\\|\\s*`([^`]+)`\\s*\\|\", table, flags=re.MULTILINE))\n\n\ndef shipped_provider_tables(providers_md: str) -> set[str]:\n    table = markdown_section(providers_md, \"## Shipped Providers\")\n    return set(re.findall(r\"\\|\\s*`\\[providers\\.([a-z0-9_]+)\\]`\\s*\\|\", table))\n\n\ndef static_registry_provider_rows(providers_md: str) -> set[str]:\n    table = markdown_section(providers_md, \"## Static Model Registry\")\n    return set(re.findall(r\"^\\|\\s*`([^`]+)`\\s*\\|\", table, flags=re.MULTILINE))\n\n","sourceCodeStart":178,"sourceCodeEnd":214,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/scripts/check-provider-registry.py#L178-L214","documentation":"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.","triggerScenarios":"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.","commonSituations":"Making per-table provider config optional; centralizing config into a map; type renames during config-crate refactors.","solutions":["Keep ProvidersToml fields shaped as `pub <name>: ProviderConfigToml`","If the field type was renamed, update the regex in provider_tables() to the new type name","If the struct moved, update the CONFIG_RS path constant or the struct anchor string in the script"],"exampleFix":"// before\npub struct ProvidersToml {\n    pub deepseek: Option<ProviderConfigToml>,\n}\n// after\npub struct ProvidersToml {\n    pub deepseek: ProviderConfigToml,\n}","handlingStrategy":"try-catch","validationCode":"fields = re.findall(r'pub\\s+([a-z0-9_]+)\\s*:\\s*ProviderConfigToml', config_rs)\nassert fields, 'ProvidersToml shape changed — update the checker'","typeGuard":null,"tryCatchPattern":"try:\n    tables = provider_tables(config_rs)\nexcept ValueError as e:\n    inspect_struct_providers_toml(); raise","preventionTips":["Keep ProvidersToml fields as plain ProviderConfigToml types","Update the regex alongside config-type renames","Prefer adding or removing fields over reshaping the struct"],"tags":["python","rust","regex","config","static-analysis"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}