I was having some trouble running the local hamilton UI while following [these docs](https://hamilton.apache.org/hamilton-ui/ui/#local-mode) This seems only to be an issue with the UI module, the sdk seems to work fine # Current behavior Outputs: ```ConfigError: The use of `Config` class is removed for ModelSchema, use 'Meta' instead``` ## Stack Traces <details> <summary>Somewhat full trace (cut-off due to character limit)</summary> ``` │ C:\Users\Daan\web-projects\experimental_projects\my_hamilton_project\.venv\Lib\site-packages\django\core\checks\registry.py:89 in run_checks │ │ │ │ 86 │ │ │ checks = [check for check in checks if not set(check.tags).isdisjoint(tags)] │ │ 87 │ │ │ │ 88 │ │ for check in checks: │ │ ❱ 89 │ │ │ new_errors = check(app_configs=app_configs, databases=databases) │ │ 90 │ │ │ if not isinstance(new_errors, Iterable): │ │ 91 │ │ │ │ raise TypeError( │ │ 92 │ │ │ │ │ "The function %r did not return a list. All functions " │ │ │ │ ╭─────────────────────────────────────────────── locals ───────────────────────────────────────────────╮ │ │ │ app_configs = None │ │ │ │ checks = [ │ │ │ │ │ <function check_all_models at 0x0000019E10D71080>, │ │ │ │ │ <function check_csp_settings at 0x0000019E10D720C0>, │ │ │ │ │ <function check_middleware at 0x0000019E126F7100>, │ │ │ │ │ <function check_url_config at 0x0000019E11DBA980>, │ │ │ │ │ <function check_models_permissions at 0x0000019E126F49A0>, │ │ │ │ │ <function check_generic_foreign_keys at 0x0000019E126F71A0>, │ │ │ │ │ <function check_finders at 0x0000019E126F79C0>, │ │ │ │ │ <function check_database_backends at 0x0000019E10D43A60>, │ │ │ │ │ <function check_lazy_references at 0x0000019E10D71260>, │ │ │ │ │ <function check_default_cache_is_configured at 0x0000019E10D40360>, │ │ │ │ │ ... +18 │ │ │ │ ] │ │ │ │ databases = ['default'] │ │ │ │ errors = [] │ │ │ │ include_deployment_checks = False │ │ │ │ new_errors = [] │ │ │ │ self = <django.core.checks.registry.CheckRegistry object at 0x0000019E10BC52B0> │ │ │ │ tags = None │ │ │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────╯ │ │ │ │ C:\Users\Daan\web-projects\experimental_projects\my_hamilton_project\.venv\Lib\site-packages\django\core\checks\urls.py:16 in check_url_config │ │ │ │ 13 │ │ from django.urls import get_resolver ╭────────────────────────── locals ──────────────────────────╮ │ │ 14 │ │ │ app_configs = None │ │ │ 15 │ │ resolver = get_resolver() │ kwargs = {'databases': ['default']} │ │ │ ❱ 16 │ │ return check_resolver(resolver) │ resolver = <URLResolver 'server.urls' (None:None) '^/'> │ │ │ 17 │ return [] ╰────────────────────────────────────────────────────────────╯ │ │ 18 │ │ 19 │ │ │ │ C:\Users\Daan\web-projects\experimental_projects\my_hamilton_project\.venv\Lib\site-packages\django\core\checks\urls.py:26 in check_resolver │ │ │ │ 23 │ """ │ │ 24 │ check_method = getattr(resolver, "check", None) │ │ 25 │ if check_method is not None: │ │ ❱ 26 │ │ return check_method() │ │ 27 │ elif not hasattr(resolver, "resolve"): │ │ 28 │ │ return get_warning_for_invalid_pattern(resolver) │ │ 29 │ else: │ │ │ │ ╭──────────────────────────────────────────── locals ─────────────────────────────────────────────╮ │ │ │ check_method = <bound method URLResolver.check of <URLResolver 'server.urls' (None:None) '^/'>> │ │ │ │ resolver = <URLResolver 'server.urls' (None:None) '^/'> │ │ │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ │ │ │ │ C:\Users\Daan\web-projects\experimental_projects\my_hamilton_project\.venv\Lib\site-packages\django\urls\resolvers.py:541 in check │ │ │ │ 538 │ ╭──────────────────────── locals ─────────────────────────╮ │ │ 539 │ def check(self): │ messages = [] │ │ │ 540 │ │ messages = [] │ self = <URLResolver 'server.urls' (None:None) '^/'> │ │ │ ❱ 541 │ │ for pattern in self.url_patterns: ╰─────────────────────────────────────────────────────────╯ │ │ 542 │ │ │ messages.extend(check_resolver(pattern)) │ │ 543 │ │ return messages or self.pattern.check() │ │ 544 │ │ │ │ C:\Users\Daan\web-projects\experimental_projects\my_hamilton_project\.venv\Lib\site-packages\django\utils\functional.py:47 in __get__ │ │ │ │ 44 │ │ """ │ │ 45 │ │ if instance is None: │ │ 46 │ │ │ return self │ │ ❱ 47 │ │ res = instance.__dict__[self.name] = self.func(instance) │ │ 48 │ │ return res │ │ 49 │ │ 50 │ │ │ │ ╭───────────────────────────────────── locals ──────────────────────────────────────╮ │ │ │ instance = <URLResolver 'server.urls' (None:None) '^/'> │ │ │ │ self = <django.utils.functional.cached_property object at 0x0000019E122FFD90> │ │ │ ╰───────────────────────────────────────────────────────────────────────────────────╯ │ │ │ │ C:\Users\Daan\web-projects\experimental_projects\my_hamilton_project\.venv\Lib\site-packages\django\urls\resolvers.py:729 in url_patterns │ │ │ │ 726 │ @cached_property ╭────────────────────── locals ───────────────────────╮ │ │ 727 │ def url_patterns(self): │ self = <URLResolver 'server.urls' (None:None) '^/'> │ │ │ 728 │ │ # urlconf_module might be a valid set of patterns, so we default to it ╰─────────────────────────────────────────────────────╯ │ │ ❱ 729 │ │ patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module) │ │ 730 │ │ try: │ │ 731 │ │ │ iter(patterns) │ │ 732 │ │ except TypeError as e: │ │ │ │ C:\Users\Daan\web-projects\experimental_projects\my_hamilton_project\.venv\Lib\site-packages\django\utils\functional.py:47 in __get__ │ │ │ │ 44 │ │ """ │ │ 45 │ │ if instance is None: │ │ 46 │ │ │ return self │ │ ❱ 47 │ │ res = instance.__dict__[self.name] = self.func(instance) │ │ 48 │ │ return res │ │ 49 │ │ 50 │ │ │ │ ╭───────────────────────────────────── locals ──────────────────────────────────────╮ │ │ │ instance = <URLResolver 'server.urls' (None:None) '^/'> │ │ │ │ self = <django.utils.functional.cached_property object at 0x0000019E122FFD20> │ │ │ ╰───────────────────────────────────────────────────────────────────────────────────╯ │ │ │ │ C:\Users\Daan\web-projects\experimental_projects\my_hamilton_project\.venv\Lib\site-packages\django\urls\resolvers.py:722 in urlconf_module │ │ │ │ 719 │ @cached_property ╭────────────────────── locals ───────────────────────╮ │ │ 720 │ def urlconf_module(self): │ self = <URLResolver 'server.urls' (None:None) '^/'> │ │ │ 721 │ │ if isinstance(self.urlconf_name, str): ╰─────────────────────────────────────────────────────╯ │ │ ❱ 722 │ │ │ return import_module(self.urlconf_name) │ │ 723 │ │ else: │ │ 724 │ │ │ return self.urlconf_name │ │ 725 │ │ │ │ C:\Users\Daan\AppData\Roaming\uv\python\cpython-3.13.0-windows-x86_64-none\Lib\importlib\__init__.py:88 in import_module │ │ │ │ 85 │ │ │ if character != '.': ╭──────── locals ─────────╮ │ │ 86 │ │ │ │ break │ level = 0 │ │ │ 87 │ │ │ level += 1 │ name = 'server.urls' │ │ │ ❱ 88 │ return _bootstrap._gcd_import(name[level:], package, level) │ package = None │ │ │ 89 ╰─────────────────────────╯ │ │ 90 │ │ 91 _RELOADING = {} │ │ in _gcd_import:1387 │ │ ╭──────── locals ─────────╮ │ │ │ level = 0 │ │ │ │ name = 'server.urls' │ │ │ │ package = None │ │ │ ╰─────────────────────────╯ │ │ in _find_and_load:1360 │ │ ╭──────────────────── locals ────────────────────╮ │ │ │ module = <object object at 0x0000019E72920060> │ │ │ │ name = 'server.urls' │ │ │ ╰────────────────────────────────────────────────╯ │ │ in _find_and_load_unlocked:1331 │ │ ╭────────────────────────────────────────────────────────────────────────────── locals ───────────────────────────────────────────────────────────────────────────────╮ │ │ │ child = 'urls' │ │ │ │ name = 'server.urls' │ │ │ │ parent = 'server' │ │ │ │ parent_module = <module 'server' from │ │ │ │ 'C:\\Users\\Daan\\web-projects\\experimental_projects\\my_hamilton_project\\.venv\\Lib\\site-packages\\hamilton_ui\\server\\__init__.py'> │ │ │ │ parent_spec = ModuleSpec(name='server', loader=<_frozen_importlib_external.SourceFileLoader object at 0x0000019E10D7D070>, │ │ │ │ origin='C:\\Users\\Daan\\web-projects\\experimental_projects\\my_hamilton_project\\.venv\\Lib\\site-packages\\hamilton_ui\\server\\__init__.py', │ │ │ │ submodule_search_locations=['C:\\Users\\Daan\\web-projects\\experimental_projects\\my_hamilton_project\\.venv\\Lib\\site-packages\\hamilton_ui\\se… │ │ │ │ path = ['C:\\Users\\Daan\\web-projects\\experimental_projects\\my_hamilton_project\\.venv\\Lib\\s'+31] │ │ │ │ spec = ModuleSpec(name='server.urls', loader=<_frozen_importlib_external.SourceFileLoader object at 0x0000019E12A36810>, │ │ │ │ origin='C:\\Users\\Daan\\web-projects\\experimental_projects\\my_hamilton_project\\.venv\\Lib\\site-packages\\hamilton_ui\\server\\urls.py') │ │ │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ │ │ in _load_unlocked:935 │ │ ╭────────────────────────────────────────────────────────────────────────────── locals ───────────────────────────────────────────────────────────────────────────────╮ │ │ │ module = <module 'server.urls' from │ │ │ │ 'C:\\Users\\Daan\\web-projects\\experimental_projects\\my_hamilton_project\\.venv\\Lib\\site-packages\\hamilton_ui\\server\\urls.py'> │ │ │ │ spec = ModuleSpec(name='server.urls', loader=<_frozen_importlib_external.SourceFileLoader object at 0x0000019E12A36810>, │ │ │ │ origin='C:\\Users\\Daan\\web-projects\\experimental_projects\\my_hamilton_project\\.venv\\Lib\\site-packages\\hamilton_ui\\server\\urls.py') │ │ │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ │ │ in exec_module:1022 │ │ ╭────────────────────────────────────────────────────────────────────────────── locals ───────────────────────────────────────────────────────────────────────────────╮ │ │ │ code = <code object <module> at 0x0000019E0ECFF170, file │ │ │ │ "C:\Users\Daan\web-projects\experimental_projects\my_hamilton_project\.venv\Lib\site-packages\hamilton_ui\server\urls.py", line 1> │ │ │ │ module = <module 'server.urls' from │ │ │ │ 'C:\\Users\\Daan\\web-projects\\experimental_projects\\my_hamilton_project\\.venv\\Lib\\site-packages\\hamilton_ui\\server\\urls.py'> │ │ │ │ self = <_frozen_importlib_external.SourceFileLoader object at 0x0000019E12A36810> │ │ │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ │ │ in _call_with_frames_removed:488 │ │ ╭────────────────────────────────────────────────────────────────────────────── locals ───────────────────────────────────────────────────────────────────────────────╮ │ │ │ args = ( │ │ │ │ │ <code object <module> at 0x0000019E0ECFF170, file │ │ │ │ "C:\Users\Daan\web-projects\experimental_projects\my_hamilton_project\.venv\Lib\site-packages\hamilton_ui\server\urls.py", line 1>, │ │ │ │ │ { │ │ │ │ │ │ '__name__': 'server.urls', │ │ │ │ │ │ '__doc__': 'server URL Configuration\n\nThe `urlpatterns` list routes URLs to views. For more '+543, │ │ │ │ │ │ '__package__': 'server', │ │ │ │ │ │ '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000019E12A36810>, │ │ │ │ │ │ '__spec__': ModuleSpec(name='server.urls', loader=<_frozen_importlib_external.SourceFileLoader object at 0x0000019E12A36810>, │ │ │ │ origin='C:\\Users\\Daan\\web-projects\\experimental_projects\\my_hamilton_project\\.venv\\Lib\\site-packages\\hamilton_ui\\server\\urls.py'), │ │ │ │ │ │ '__file__': 'C:\\Users\\Daan\\web-projects\\experimental_projects\\my_hamilton_project\\.venv\\Lib\\s'+39, │ │ │ │ │ │ '__cached__': 'C:\\Users\\Daan\\web-projects\\experimental_projects\\my_hamilton_project\\.venv\\Lib\\s'+64, │ │ │ │ │ │ '__builtins__': { │ │ │ │ │ │ │ '__name__': 'builtins', │ │ │ │ │ │ │ '__doc__': 'Built-in functions, types, exceptions, and other objects.\n\nThis module provides '+346, │ │ │ │ │ │ │ '__package__': '', │ │ │ │ │ │ │ '__loader__': <class '_frozen_importlib.BuiltinImporter'>, │ │ │ │ │ │ │ '__spec__': ModuleSpec(name='builtins', loader=<class '_frozen_importlib.BuiltinImporter'>, origin='built-in'), │ │ │ │ │ │ │ '__build_class__': <built-in function __build_class__>, │ │ │ │ │ │ │ '__import__': <built-in function __import__>, │ │ │ │ │ │ │ 'abs': <built-in function abs>, │ │ │ │ │ │ │ 'all': <built-in function all>, │ │ │ │ │ │ │ 'any': <built-in function any>, │ │ │ │ │ │ │ ... +150 │ │ │ │ │ │ }, │ │ │ │ │ │ 'settings': <LazySettings "server.settings_mini">, │ │ │ │ │ │ 'static': <function static at 0x0000019E129D37E0>, │ │ │ │ │ │ ... +5 │ │ │ │ │ } │ │ │ │ ) │ │ │ │ f = <built-in function exec> │ │ │ │ kwds = {} │ │ │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ │ │ │ │ C:\Users\Daan\web-projects\experimental_projects\my_hamilton_project\.venv\Lib\site-packages\hamilton_ui\server\urls.py:24 in <module> │ │ │ │ 21 from django.views.generic import TemplateView │ │ 22 from django.views.static import serve │ │ 23 │ │ ❱ 24 from . import api, default_views │ │ 25 │ │ 26 # TODO -- ensure we didn't break the actual deployment │ │ 27 if settings.HAMILTON_ENV == "mini": │ │ │ │ ╭────────────────────────────────────────────────────────────────────────────── locals ───────────────────────────────────────────────────────────────────────────────╮ │ │ │ admin = <module 'django.contrib.admin' from │ │ │ │ 'C:\\Users\\Daan\\web-projects\\experimental_projects\\my_hamilton_project\\.venv\\Lib\\site-packages\\django\\contrib\\admin\\__init__.py'> │ │ │ │ path = functools.partial(<function _path at 0x0000019E1240C4A0>, Pattern=<class 'django.urls.resolvers.RoutePattern'>) │ │ │ │ re_path = functools.partial(<function _path at 0x0000019E1240C4A0>, Pattern=<class 'django.urls.resolvers.RegexPattern'>) │ │ │ │ settings = <LazySettings "server.settings_mini"> │ │ │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ │ │ │ │ C:\Users\Daan\web-projects\experimental_projects\my_hamilton_project\.venv\Lib\site-packages\hamilton_ui\server\api.py:3 in <module> │ │ │ │ 1 from django.conf import settings ╭───────────────────── locals ─────────────────────╮ │ │ 2 from ninja import NinjaAPI │ settings = <LazySettings "server.settings_mini"> │ │ │ ❱ 3 from trackingserver_auth import api as auth_api ╰──────────────────────────────────────────────────╯ │ │ 4 from trackingserver_base import api as base_api │ │ 5 │ │ 6 try: │ │ │ │ C:\Users\Daan\web-projects\experimental_projects\my_hamilton_project\.venv\Lib\site-packages\hamilton_ui\trackingserver_auth\api.py:6 in <module> │ │ │ │ 3 │ │ 4 from ninja import Router │ │ 5 from trackingserver_auth.models import APIKey │ │ ❱ 6 from trackingserver_auth.schema import ApiKeyIn, ApiKeyOut, PhoneHomeResult, WhoAmIResul │ │ 7 from trackingserver_base.auth.api_keys import create_api_key_for_user │ │ 8 from trackingserver_base.permissions.base import permission │ │ 9 from trackingserver_base.permissions.permissions import ( │ │ │ │ ╭───────────────────────────────────────────────────────────────────── locals ─────────────────────────────────────────────────────────────────────╮ │ │ │ logging = <module 'logging' from 'C:\\Users\\Daan\\AppData\\Roaming\\uv\\python\\cpython-3.13.0-windows-x86_64-none\\Lib\\logging\\__init__.py'> │ │ │ │ typing = <module 'typing' from 'C:\\Users\\Daan\\AppData\\Roaming\\uv\\python\\cpython-3.13.0-windows-x86_64-none\\Lib\\typing.py'> │ │ │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ │ │ │ │ C:\Users\Daan\web-projects\experimental_projects\my_hamilton_project\.venv\Lib\site-packages\hamilton_ui\trackingserver_auth\schema.py:11 in <module> │ │ │ │ 8 ########################################## │ │ 9 # These correspond (ish) to DB models # │ │ 10 ########################################## │ │ ❱ 11 class UserOut(ModelSchema): │ │ 12 │ class Config: │ │ 13 │ │ model = User │ │ 14 │ │ model_fields = ["id", "email", "first_name", "last_name"] │ │ │ │ ╭────────────────────────────────────────────────────────────── locals ───────────────────────────────────────────────────────────────╮ │ │ │ typing = <module 'typing' from 'C:\\Users\\Daan\\AppData\\Roaming\\uv\\python\\cpython-3.13.0-windows-x86_64-none\\Lib\\typing.py'> │ │ │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ │ │ │ │ C:\Users\Daan\web-projects\experimental_projects\my_hamilton_project\.venv\Lib\site-packages\ninja\orm\metaclass.py:78 in __new__ │ │ │ │ 75 │ │ │ │ and issubclass(base, ModelSchema) │ │ 76 │ │ │ │ and base == ModelSchema │ │ 77 │ │ │ ): │ │ ❱ 78 │ │ │ │ meta_conf = MetaConf.from_schema_class(name, namespace) │ │ 79 │ │ │ │ │ │ 80 │ │ │ │ custom_fields = [] │ │ 81 │ │ │ │ annotations = namespace.get("__annotations__", {}) │ │ │ │ ╭──────────────────────────────────── locals ────────────────────────────────────╮ │ │ │ bases = (<class 'ninja.orm.metaclass.ModelSchema'>,) │ │ │ │ kwargs = {} │ │ │ │ name = 'UserOut' │ │ │ │ namespace = { │ │ │ │ │ '__module__': 'trackingserver_auth.schema', │ │ │ │ │ '__qualname__': 'UserOut', │ │ │ │ │ '__firstlineno__': 11, │ │ │ │ │ 'Config': <class 'trackingserver_auth.schema.UserOut.Config'>, │ │ │ │ │ '__static_attributes__': (), │ │ │ │ │ 'model_config': { │ │ │ │ │ │ 'from_attributes': True, │ │ │ │ │ │ 'model': <class 'trackingserver_auth.models.User'>, │ │ │ │ │ │ 'model_fields': [ │ │ │ │ │ │ │ 'id', │ │ │ │ │ │ │ 'email', │ │ │ │ │ │ │ 'first_name', │ │ │ │ │ │ │ 'last_name' │ │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ '__class_vars__': set(), │ │ │ │ │ '__private_attributes__': {} │ │ │ │ } │ │ │ ╰────────────────────────────────────────────────────────────────────────────────╯ │ │ │ │ C:\Users\Daan\web-projects\experimental_projects\my_hamilton_project\.venv\Lib\site-packages\ninja\orm\metaclass.py:23 in from_schema_class │ │ │ │ 20 │ @staticmethod │ │ 21 │ def from_schema_class(name: str, namespace: dict) -> "MetaConf": │ │ 22 │ │ if "Config" in namespace: │ │ ❱ 23 │ │ │ raise ConfigError( # pragma: no cover │ │ 24 │ │ │ │ "The use of `Config` class is removed for ModelSchema, use 'Meta' instea │ │ 25 │ │ │ ) │ │ 26 │ │ if "Meta" in namespace: │ │ │ │ ╭──────────────────────────────────── locals ────────────────────────────────────╮ │ │ │ name = 'UserOut' │ │ │ │ namespace = { │ │ │ │ │ '__module__': 'trackingserver_auth.schema', │ │ │ │ │ '__qualname__': 'UserOut', │ │ │ │ │ '__firstlineno__': 11, │ │ │ │ │ 'Config': <class 'trackingserver_auth.schema.UserOut.Config'>, │ │ │ │ │ '__static_attributes__': (), │ │ │ │ │ 'model_config': { │ │ │ │ │ │ 'from_attributes': True, │ │ │ │ │ │ 'model': <class 'trackingserver_auth.models.User'>, │ │ │ │ │ │ 'model_fields': [ │ │ │ │ │ │ │ 'id', │ │ │ │ │ │ │ 'email', │ │ │ │ │ │ │ 'first_name', │ │ │ │ │ │ │ 'last_name' │ │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ '__class_vars__': set(), │ │ │ │ │ '__private_attributes__': {} │ │ │ │ } │ │ │ ╰────────────────────────────────────────────────────────────────────────────────╯ │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ConfigError: The use of `Config` class is removed for ModelSchema, use 'Meta' instead ``` </details> ## Screenshots (If applicable) ## Steps to replicate behavior 1. `uv init my_hamilton_project` 2. `cd my_hamilton_project` 3. `uv add "sf-hamilton[sdk,ui]>=1.89.0"` 4. activate venv 5. `hamilton ui` or `uv run hamilton ui` ## Library & System Information * Hamilton 1.89.0 * uv 0.9.8 (85c5d3228 2025-11-07) * python 3.13 # Expected behavior For the UI service to run # Additional context Same problem when using pip with venv. Here is a little Dockerfile which reproduces the error ```Dockerfile FROM python:3.13 WORKDIR /usr/local/app RUN pip install "sf-hamilton[ui,sdk]==1.89.0" EXPOSE 8080 CMD ["hamilton", "ui", "--port", "8080"] ```