<@ULVA73B9P> sometimes i get this error sometimes ...
# marvin-ai
j
@Marvin sometimes i get this error sometimes not. can you tell me what could be the source? TypeError: Type parameter ~R without a default follows type parameter with a default ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/dju/code/dlthub/dlt-plus/.venv/lib/python3.12/site-packages/prefect/utilities/callables.py", line 210, in call_with_parameters return fn(*args, **kwargs) File "/home/dju/.pyenv/versions/3.12.9/lib/python3.12/typing.py", line 1120, in _generic_class_getitem return _GenericAlias(cls, params) ^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/dju/.pyenv/versions/3.12.9/lib/python3.12/typing.py", line 1275, in init self.parameters = _collect_parameters(args) ^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/dju/code/dlthub/dlt-plus/.venv/lib/python3.12/site-packages/pip/_vendor/typing_extensions.py", line 3072, in _collect_parameters raise TypeError(f'Type parameter {t!r} without a default' TypeError: Type parameter ~R without a default follows type parameter with a default
@Marvin sometimes i get this error sometimes not. can you tell me what could be the source? TypeError: Type parameter ~R without a default follows type parameter with a default
m
thought for 215.2 seconds
thought for 306.8 seconds
Short version: Python is complaining because you’ve defined a generic where a type parameter without a default comes after one with a default. Just like function parameters, non-defaults must come before defaults. Why you see it “sometimes” - The rule is enforced at runtime in Python 3.12+ (PEP 695/696). If you run the same code on an older interpreter, or with an older typing_extensions, it may not raise. - Different environments or containers with slightly different Python/typing_extensions versions will behave differently. What triggers it - Using defaulted TypeVars (or ParamSpec/TypeVarTuple) with the classic typing API:
Copy code
from typing import TypeVar, Generic
  T = TypeVar("T", default=int)   # has a default
  R = TypeVar("R")                # no default

  class Pair(Generic[T, R]):      # BAD: non-default after default
      pass
- Using the new 3.12 type parameter syntax (PEP 695):
Copy code
def f<x: T|T=int, R> -> R:     # BAD
      ...
How to fix it - Put all non-default type parameters first, then the ones with defaults; or give defaults to all following parameters; or remove the defaults entirely.
Copy code
# Classic API
  from typing import TypeVar, Generic
  R = TypeVar("R")                # no default first
  T = TypeVar("T", default=int)   # defaulted after

  class Pair(Generic[R, T]):      # GOOD
      pass

  # New 3.12 syntax
  def f<x: T|R, T=int> -> R:     # GOOD
      ...
How to confirm your environment - Check versions (this often explains the “sometimes”):
Copy code
python -c "import sys, typing_extensions as te; print(sys.version); print(getattr(te, '__version__', 'no typing_extensions'))"
If you’re on Python 3.12+ or using a recent typing_extensions (backporting PEP 696), the rule will be enforced. Authoritative references - PEP 695 (Type Parameter Syntax): https://peps.python.org/pep-0695/ - PEP 696 (Type defaults for TypeVarLikes): https://peps.python.org/pep-0696/ - typing docs for TypeVar defaults (3.12+): https://docs.python.org/3/library/typing.html#typing.TypeVar - typing_extensions changelog (backports of these features): https://github.com/python/typing_extensions/blob/main/CHANGELOG.md If you can share: - The snippet where the generic is declared - Your Python version and typing_extensions version I can point at the exact parameter ordering that’s causing the fuss and suggest the minimal change.
Short answer: this isn’t a Prefect bug. It’s Python’s typing system (PEP 696 “default type parameters”) complaining at runtime, usually because two different copies of typing_extensions are involved and disagree about whether a TypeVar has a default. The error text is raised when a non‑default type parameter follows a default one; the intermittent part typically comes from mixing modules that carry their own copy of typing_extensions (notably pip’s vendored copy) with the regular typing_extensions on sys.path. Why you’re seeing it: - PEP 696 enforces “defaults must come last” for Generic type parameters. At runtime, typing/typing_extensions validates this when you subscript a generic class or alias. - Your traceback shows the check coming from pip’s vendored typing_extensions: /site-packages/pip/_vendor/typing_extensions.py … raise TypeError(...) That’s a red flag for “multiple typing_extensions in one process.” When one module creates TypeVars using one typing_extensions and another validates them using a different typing_extensions, the “NoDefault” sentinel doesn’t match and the runtime thinks one of your earlier params has a default when it actually doesn’t (or vice versa). Hence the sporadic blow‑ups. - There’s an open ecosystem issue about this class of failures: - python/typing_extensions#536 (discussion about cross‑module NoDefault detection) - Related PR improving PEP 696 runtime behavior: PR #293 What to do: 1) Verify if you’re loading two copies of typing_extensions Run this little probe:
Copy code
python - <<'PY'
   import sys
   import typing_extensions as te
   print("Python:", sys.version)
   print("typing_extensions:", getattr(te, "__version__", "unknown"), te.__file__)
   try:
       import pip._vendor.typing_extensions as vte
       print("pip vendored typing_extensions:", vte.__file__)
       print("Same module object?", te is vte)
   except Exception as e:
       print("pip vendored not importable:", e)
   PY
If both are importable and they’re not the same object, you’ve found the culprit. 2) Upgrade to a single, current typing_extensions and pip
Copy code
pip install -U pip typing-extensions
Then re‑run the probe. Ideally, only one copy is ever imported during your run. 3) Make sure no dependency is importing pip._vendor.typing_extensions - Grep your codebase and known deps for that import path. If a library does this, upgrade it. If it’s pinned and you’re stuck, consider reporting upstream; this import is brittle for exactly this reason. 4) Double‑check you’re not declaring a Generic with defaults in the wrong order If you have anything like:
Copy code
from typing import Generic, TypeVar
   T = TypeVar("T", default=int)
   R = TypeVar("R")
   class Bad(Generic[T, R]):  # will raise
       pass
Fix by moving defaults to the end:
Copy code
class Good(Generic[R, T]):
       pass
This won’t explain the intermittency, but it’s worth ruling out. 5) If you must ship today and can’t untangle the imports A pragmatic (temporary) workaround some folks use is to ensure the same NoDefault sentinel is used across modules by forcing the non‑vendored typing_extensions to be imported first and, if necessary, avoiding libraries that import pip._vendor.typing_extensions. I wouldn’t recommend monkey‑patching in production unless you’re desperate. Why Prefect shows up in the stack: - Prefect’s
call_with_parameters
is just where your function call passes through; it triggers the subscript/validation of some generic in your environment. Prefect 3.x itself isn’t the source of this error. If you share: - Your Prefect, pydantic, typing-extensions versions - The output of the probe above - Any custom Generic/TypeVar definitions you have …I can help pinpoint the exact offender and suggest a precise pin/upgrade.