Russell Brooks
04/23/2026, 7:53 AMMarvin
04/23/2026, 7:53 AMMarvin
04/23/2026, 7:56 AMBlock globally. In practice, you should either:
1. create a subclass per block type that needs custom fallback behavior, or
2. put the fallback logic in one shared helper/wrapper and call that for any block class.
Block.load(...) is a classmethod that returns the specific subclass that called it, so while you can technically monkey-patch the upstream Block base class, that would affect all blocks globally and is not a supported or safe extension pattern.
A better pattern is:
python
from prefect.blocks.core import Block
def load_block_with_fallback(block_cls: type[Block], name: str, **kwargs):
try:
return block_cls.load(name, **kwargs)
except Exception:
# fallback logic here
return ...
That lets you write the fallback logic once without subclassing every block unless you specifically want a custom API like MySecretBlock.load(...).
If you do want it attached to the class API, then yes, you’d generally need a custom subclass for each block type, for example:
python
from prefect.blocks.system import Secret
class FallbackSecret(Secret):
@classmethod
def load(cls, name: str, validate: bool = True, client=None):
try:
return super().load(name, validate=validate, client=client)
except Exception:
return cls(value="fallback-secret")
A few important caveats:
- Monkey-patching Block.load upstream is not recommended
- it changes behavior for every block
- it can be hard to debug
- you’d also need to think about aload(...) for async contexts
- Prefect does not provide a built-in alternate-location fallback for blocks if the API/database is unavailable
- Often the cleanest fallback source is environment variables or a local config file rather than trying to alter block internals
So the practical answer is:
- If you want one reusable implementation: use a helper/factory function once
- If you want the behavior on the class itself: make a subclass per block type
- Do not patch the base Block class globally unless you’re willing to own the maintenance risk
Relevant API docs:
- Prefect Blocks docs
If you want, I can sketch a generic fallback loader that works with Secret, JSON, String, and your own custom blocks without needing one subclass per type.Russell Brooks
04/23/2026, 8:05 AMMarvin
04/23/2026, 8:05 AMMarvin
04/23/2026, 8:05 AMload_block_with_fallback is the minimal generic idea:
python
def load_block_with_fallback(block_cls, name, **kwargs):
try:
return block_cls.load(name, **kwargs)
except Exception:
return ...
That says: “try Prefect first, otherwise do something else.”
But it leaves the fallback undefined.
A more complete generic fallback loader would add things like:
- different fallback sources per block type
- conversion from env/config values into the right block instance
- narrower exception handling
- optional sync/async support
- consistent logging/errors
For example:
python
import json
import os
from prefect.blocks.system import Secret, JSON, String
def load_block_with_fallback(block_cls, name: str, validate: bool = True, client=None):
try:
return block_cls.load(name, validate=validate, client=client)
except Exception as exc:
env_name = name.upper().replace("-", "_")
if block_cls is Secret:
value = os.getenv(env_name)
if value is None:
raise
return Secret(value=value)
if block_cls is String:
value = os.getenv(env_name)
if value is None:
raise
return String(value=value)
if block_cls is JSON:
value = os.getenv(env_name)
if value is None:
raise
return JSON(value=json.loads(value))
raise
So:
- the first version is a pattern stub
- the generic fallback loader is a real reusable implementation
If you want to support many block types without subclassing each one, the second approach is what I meant.
One important improvement I’d recommend over my earlier sketch: don’t catch bare Exception unless you really mean it. Prefer catching API/unavailability-related errors only, so you don’t mask validation bugs or coding mistakes.
If you want, I can write a production-ready version that:
- handles Secret, String, and JSON
- uses env vars or local files as fallback
- only catches the right Prefect/client errors
- includes an async aload equivalent too