{"record":{"id":"f1ac2e6d7c75698a","repo":"Hmbown/CodeWhale","slug":"provider-invocations-returned-no-providers","errorCode":null,"errorMessage":"provider!() invocations returned no providers","messagePattern":"provider!\\(\\) invocations returned no providers","errorType":"console","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"scripts/check-provider-registry.py","lineNumber":203,"sourceCode":"        # the wire policy is not fixed, so provider!() cannot express them.\n        (\"ModelstudioTokenPlan\", \"modelstudio-token-plan\"),\n        (\"ModelstudioTokenPlanAnthropic\", \"modelstudio-token-plan-anthropic\"),\n        (\"ModelstudioCodingPlan\", \"modelstudio-coding-plan\"),\n        (\"ModelstudioCodingPlanAnthropic\", \"modelstudio-coding-plan-anthropic\"),\n    ]:\n        match = re.search(\n            rf'impl\\s+Provider\\s+for\\s+{variant_name}.*?fn\\s+id.*?\\\"({id_literal})\\\"',\n            provider_rs, re.DOTALL,\n        )\n        if match:\n            ids[variant_name] = match.group(1)\n        elif variant_name not in ids:\n            raise ValueError(\n                f\"expected a hand-written `impl Provider for {variant_name}` \"\n                f\"with id {id_literal!r}; the guard's floor is stale\"\n            )\n    if not ids:\n        raise ValueError(\"provider!() invocations returned no providers\")\n    return ids\n\n\ndef provider_kind_catalog_ids(\n    provider_kind_rs: str, variant_to_id: dict[str, str]\n) -> set[str]:\n    catalog = re.search(\n        r\"pub const ALL:\\s*\\[Self;\\s*\\d+\\]\\s*=\\s*\\[(.*?)\\];\",\n        provider_kind_rs,\n        flags=re.DOTALL,\n    )\n    if catalog is None:\n        raise ValueError(\"crates/config/src/provider_kind.rs: missing ProviderKind::ALL\")\n    variants = set(re.findall(r\"Self::(\\w+)\", catalog.group(1)))\n    catalog_variant_to_id = {**variant_to_id, \"Custom\": \"custom\"}\n    missing = variants - set(catalog_variant_to_id)\n    if missing:\n        raise ValueError(f\"ProviderKind::ALL uses unknown variants: {sorted(missing)}\")","sourceCodeStart":185,"sourceCodeEnd":221,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/scripts/check-provider-registry.py#L185-L221","documentation":"provider_kind_ids() finishes by asserting it actually extracted at least one variant→id pair from the provider!() invocations. This error means the regex found zero provider!() calls, i.e. the function read a source where the registry macro invocations are absent entirely — the guard is reading the wrong file or the registry format changed wholesale.","triggerScenarios":"Called from api_provider_ids or main when re.findall over the source for provider!(...) invocations returns nothing — the file passed for provider_rs has no matching invocations (wrong path, empty read, or macro call format no longer matches the regex).","commonSituations":"The config module split moved provider registrations to a different file and the guard's path constant is stale; the provider! macro call syntax changed (different arg layout/whitespace); running the script from a checkout where the registry file is empty or missing.","solutions":["Point the guard's source path (PROVIDER_RS / config source) at the file that actually contains the provider!() invocations","Update the provider!() regex in provider_kind_ids to match the current macro call format","Verify the repository checkout is complete and the registry file is non-empty before running the guard"],"exampleFix":"// before: PROVIDER_RS points to old config/providers.rs (moved in split)\n// after:  PROVIDER_RS = REPO / \"crates\" / \"config\" / \"src\" / \"provider_kind.rs\" (or the file now holding provider!() calls)","handlingStrategy":"validation","validationCode":"import re\nif not re.findall(r'provider!\\(', provider_rs):\n    print(\"no provider!() invocations found; check source path\")","typeGuard":null,"tryCatchPattern":"try:\n    ids = provider_kind_ids(provider_rs)\nexcept ValueError as e:\n    print(f\"registry source unusable: {e}\", file=sys.stderr)\n    sys.exit(1)","preventionTips":["Keep the guard's source path constants updated after module moves","Verify the registry file exists and is non-empty before scanning","Update the provider!() regex when macro call syntax changes"],"tags":["python","rust","provider-registry","empty-result","ci-guard"],"backgroundTag":"empty-result-set","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}