{"record":{"id":"843a35c586ce46b8","repo":"p-e-w/heretic","slug":"self-class-name-settings-must-be-an-inst","errorCode":null,"errorMessage":"{self.__class__.__name__}.settings must be an instance of {settings_model.__name__}","messagePattern":"(.+?)\\.settings must be an instance of (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/heretic/plugin.py","lineNumber":225,"sourceCode":"\n        Defaults to False; override to True in your plugin class if any of the\n        above DO NOT apply.\n        \"\"\"\n        return False\n\n    def __init__(\n        self, *, heretic_settings: HereticSettings, settings: BaseModel | None = None\n    ):\n        # Plugins that declare a settings schema should always receive\n        # validated plugin settings from the evaluator.\n        settings_model = self.__class__.get_settings_model()\n        if settings_model is not None:\n            if settings is None:\n                raise ValueError(\n                    f\"{self.__class__.__name__} requires settings to be validated\"\n                )\n            if not isinstance(settings, settings_model):\n                raise TypeError(\n                    f\"{self.__class__.__name__}.settings must be an instance of \"\n                    f\"{settings_model.__name__}\"\n                )\n        self.settings = settings\n        self.heretic_settings = heretic_settings\n\n    @classmethod\n    def validate_contract(cls) -> None:\n        \"\"\"\n        Validate the plugin contract.\n\n        - Plugins must not define a constructor (`__init__`). Initialization is\n          handled by `Plugin.__init__` and an optional `init(ctx)` method.\n        - Plugin subclasses may define `settings: <BaseModelSubclass>` to declare a settings schema.\n        \"\"\"\n        if \"__init__\" in cls.__dict__:\n            raise TypeError(\n                f\"{cls.__name__} must not define __init__(). \"","sourceCodeStart":207,"sourceCodeEnd":243,"githubUrl":"https://github.com/p-e-w/heretic/blob/bedb94ef117a271532ac2058447fbc165d5051bd/src/heretic/plugin.py#L207-L243","documentation":"The plugin declares a settings model, settings were provided, but they are not an instance of that exact pydantic model class. Plugin.__init__ raises TypeError to guarantee plugins only ever see settings validated against their declared schema.","triggerScenarios":"Passing a raw dict, a different BaseModel subclass, or another plugin's settings instance into __init__; a custom evaluator wiring settings from the wrong [namespace] table; subclassing a plugin but reusing the parent's settings class while the evaluator supplies the child's.","commonSituations":"Refactors that renamed or replaced the settings model while old callers construct the old type; tests passing mocks/dicts; two plugins with similarly named settings models getting crossed in a config.","solutions":["Construct settings with the exact model named in the error: SettingsModel(**config_dict).","Validate your TOML table through the evaluator's normal path so it instantiates the right model.","If you deliberately changed the schema, update get_settings_model()/the annotation and all construction sites together."],"exampleFix":"# before\nplugin = MyScorer(heretic_settings=hs, settings={\"threshold\": 0.5})\n# after\nplugin = MyScorer(heretic_settings=hs, settings=MyScorerSettings(threshold=0.5))","handlingStrategy":"type-guard","validationCode":"model = MyScorer.get_settings_model()\nassert isinstance(raw_settings, model), f\"expected {model.__name__}, got {type(raw_settings).__name__}\"","typeGuard":"def has_valid_settings(plugin: object, model: type) -> bool:\n    return isinstance(getattr(plugin, \"settings\", None), model)","tryCatchPattern":"try:\n    plugin = MyScorer(heretic_settings=hs, settings=raw)\nexcept TypeError as e:\n    sys.exit(f\"{e} — construct settings via {MyScorer.get_settings_model()}(**cfg)\")","preventionTips":["Always instantiate the exact settings model, never pass dicts.","When refactoring settings models, update all construction sites.","Let the evaluator build settings from TOML instead of hand-constructing them."],"tags":["plugin","settings","validation","pydantic"],"backgroundTag":"schema-validation-failed","analyzedSha":"bedb94ef117a271532ac2058447fbc165d5051bd","analyzedAt":"2026-08-29T08:38:06.692Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}