{"record":{"id":"ac59922c434eb339","repo":"github/copilot-sdk","slug":"missing-required-fields-in-modelinfo-id-id-nam","errorCode":null,"errorMessage":"Missing required fields in ModelInfo: id={id}, name={name}, capabilities={capabilities_dict}","messagePattern":"Missing required fields in ModelInfo: id=(.+?), name=(.+?), capabilities=(.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/copilot/client.py","lineNumber":1144,"sourceCode":"\n    id: str  # Model identifier (e.g., \"claude-sonnet-4.5\")\n    name: str  # Display name\n    capabilities: ModelCapabilities  # Model capabilities and limits\n    policy: ModelPolicy | None = None  # Policy state\n    billing: ModelBilling | None = None  # Billing information\n    # Supported reasoning effort levels (only present if model supports reasoning effort)\n    supported_reasoning_efforts: list[str] | None = None\n    # Default reasoning effort level (only present if model supports reasoning effort)\n    default_reasoning_effort: str | None = None\n\n    @staticmethod\n    def from_dict(obj: Any) -> ModelInfo:\n        assert isinstance(obj, dict)\n        id = obj.get(\"id\")\n        name = obj.get(\"name\")\n        capabilities_dict = obj.get(\"capabilities\")\n        if id is None or name is None or capabilities_dict is None:\n            raise ValueError(\n                f\"Missing required fields in ModelInfo: id={id}, name={name}, \"\n                f\"capabilities={capabilities_dict}\"\n            )\n        capabilities = ModelCapabilities.from_dict(capabilities_dict)\n        policy_dict = obj.get(\"policy\")\n        policy = ModelPolicy.from_dict(policy_dict) if policy_dict else None\n        billing_dict = obj.get(\"billing\")\n        billing = ModelBilling.from_dict(billing_dict) if billing_dict else None\n        supported_reasoning_efforts = obj.get(\"supportedReasoningEfforts\")\n        default_reasoning_effort = obj.get(\"defaultReasoningEffort\")\n        return ModelInfo(\n            id=str(id),\n            name=str(name),\n            capabilities=capabilities,\n            policy=policy,\n            billing=billing,\n            supported_reasoning_efforts=supported_reasoning_efforts,\n            default_reasoning_effort=default_reasoning_effort,","sourceCodeStart":1126,"sourceCodeEnd":1162,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/python/copilot/client.py#L1126-L1162","documentation":"ModelInfo.from_dict requires 'id', 'name', and 'capabilities' in each model entry of the model catalog and raises ValueError listing the missing values otherwise. Optional 'policy' is decoded only when present, but id/name/capabilities are mandatory to build a usable ModelInfo.","triggerScenarios":"The list-models response contains an entry missing 'id', 'name', or 'capabilities'; a minimal mock returns only {'id': ..., 'name': ...}; a server-side schema change renames or drops 'capabilities'.","commonSituations":"Version drift between client schema expectations and server model catalog; aggregating models from multiple backends where one omits capabilities; hand-written test fixtures.","solutions":["Upgrade/align the server so every model entry includes id, name, and capabilities","Skip or repair incomplete entries before calling from_dict (validate keys first)","Update mocks/fixtures to include a capabilities object compatible with ModelCapabilities.from_dict"],"exampleFix":"// before (fixture)\n{\"id\": \"gpt-4o\", \"name\": \"GPT-4o\"}\n// after\n{\"id\": \"gpt-4o\", \"name\": \"GPT-4o\", \"capabilities\": {\"supports\": {}}}\n# (capabilities object must satisfy ModelCapabilities.from_dict)","handlingStrategy":"validation","validationCode":"def model_entry_is_decodable(m: dict) -> bool:\n    return (\n        isinstance(m, dict)\n        and m.get(\"id\") is not None\n        and m.get(\"name\") is not None\n        and m.get(\"capabilities\") is not None\n    )\nmodels = [ModelInfo.from_dict(m) for m in raw if model_entry_is_decodable(m)]","typeGuard":"def is_model_entry(obj: object) -> bool:\n    return isinstance(obj, dict) and {\"id\", \"name\", \"capabilities\"} <= obj.keys()","tryCatchPattern":"try:\n    info = ModelInfo.from_dict(entry)\nexcept ValueError as e:\n    if str(e).startswith(\"Missing required fields in ModelInfo\"):\n        logger.warning(\"skipping malformed model entry: %s\", entry)\n        info = None\n    else:\n        raise","preventionTips":["Validate each catalog entry's keys before decoding","Keep client and server model-catalog schemas versioned together","Fixtures must include a capabilities object matching ModelCapabilities.from_dict"],"tags":["python","deserialization","models","schema"],"backgroundTag":"schema-validation-failed","analyzedSha":"cd8cf15dc3f9e762615790aaed0a771a0f392755","analyzedAt":"2026-09-09T18:32:31.973Z","contentChangedAt":"2026-09-09T18:32:31.973Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}