Mike B
10/30/2025, 8:06 PMstr | Secret[str] on TypedDict GitCredentials
--> deployment.py4521
|
43 | git_repo = GitRepository(
44 | url=ds.GIT_REPOSITORY,
45 | credentials={"access_token": Secret.load(ds.GIT_ACCESS_TOKEN_SECRET_NAME)},
| -----------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
| || |
| || value of type Unknown | Coroutine[Any, Any, Unknown]
| |key has declared type str | Secret[str]
| TypedDict GitCredentials
46 | branch=git_branch,
47 | )
|
info: Item declaration
--> .venv\Lib\site-packages\prefect\runner\storage.py815
|
79 | class GitCredentials(TypedDict, total=False):
80 | username: str
81 | access_token: str | Secret[str]
| ------------------------------- Item declared here
|
info: rule invalid-argument-type is enabled by default"
Code:
from prefect.runner.storage import GitRepository
from prefect.blocks.system import Secret
git_repo = GitRepository(
url=ds.GIT_REPOSITORY,
credentials={"access_token": Secret.load(ds.GIT_ACCESS_TOKEN_SECRET_NAME)},
branch=git_branch,
)Marvin
10/30/2025, 8:06 PMMarvin
10/30/2025, 8:10 PMprefect.blocks.system.Secret or prefect.runner.storage.GitRepository. However, recent typing changes (part of “unifying sync and async client methods”) can make some type checkers think Secret.load(...) could be a coroutine, which triggers the error you’re seeing.
What’s going on
- GitRepository still accepts credentials like {"access_token": str | Secret[str]}.
- Secret.load(name) still returns a Secret block at runtime, and Secret.get() returns the underlying string.
- Recent typing changes (see “Unify sync and async client methods”) can cause static type checkers to infer Unknown | Coroutine[...] for Secret.load(...), even though it works at runtime.
References
- Git repository storage source: https://github.com/PrefectHQ/prefect/blob/main/src/prefect/runner/storage.py
- Secret block source: https://github.com/PrefectHQ/prefect/blob/main/src/prefect/blocks/system.py
- Release notes mentioning the sync/async unification: https://github.com/PrefectHQ/prefect/pull/19217 and the latest changelog: https://github.com/PrefectHQ/prefect/compare/3.4.24...3.4.25
How to fix/work around the type check
Pick one of these patterns based on your code being sync or async:
- If you are in a synchronous context (most common):
from typing import cast
from prefect.blocks.system import Secret
from prefect.runner.storage import GitRepository
token_block = cast(Secret[str], Secret.load(ds.GIT_ACCESS_TOKEN_SECRET_NAME))
git_repo = GitRepository(
url=ds.GIT_REPOSITORY,
credentials={"access_token": token_block},
branch=git_branch,
)
- If you’re in an async function, await the load:
from prefect.blocks.system import Secret
from prefect.runner.storage import GitRepository
async def make_repo():
token_block = await Secret.load(ds.GIT_ACCESS_TOKEN_SECRET_NAME)
return GitRepository(
url=ds.GIT_REPOSITORY,
credentials={"access_token": token_block},
branch=git_branch,
)
- Or pass a plain string token (also satisfies the type checker):
from prefect.blocks.system import Secret
from prefect.runner.storage import GitRepository
token = Secret.load(ds.GIT_ACCESS_TOKEN_SECRET_NAME).get()
git_repo = GitRepository(
url=ds.GIT_REPOSITORY,
credentials={"access_token": token},
branch=git_branch,
)
Notes
- At runtime, Secret.load(...) is usable synchronously in Prefect 3.x; the error you’re seeing is strictly about static typing.
- If the checker is still unhappy in sync code, the typing.cast is the least invasive fix.
- If possible, confirm your Prefect version (python -c "import prefect; print(prefect.__version__)"). If you’re on a very recent 3.x (e.g., 3.4.25+), this typing behavior is expected due to the sync/async unification work.
If you can share:
- Your Prefect version
- Which type checker (pyright/mypy/etc.) and its version
- Whether this runs in a sync or async context
…I can tailor the minimal change that will satisfy your checker without suppressions.Nate
10/30/2025, 8:17 PMty itself has changed recently, as i think its still in alpha?Nate
10/30/2025, 8:18 PMMike B
10/30/2025, 8:21 PM