Amir Kamal
05/14/2026, 6:10 AMMarvin
05/14/2026, 6:10 AMMarvin
05/14/2026, 6:12 AMDatabaseCredentials block to create.
What you want instead is SqlAlchemyConnector from the prefect-sqlalchemy integration.
Example: create and save it programmatically
python
from prefect_sqlalchemy import SqlAlchemyConnector, ConnectionComponents, SyncDriver
connector = SqlAlchemyConnector(
connection_info=ConnectionComponents(
driver=SyncDriver.POSTGRESQL_PSYCOPG2,
username="myuser",
password="mypassword",
host="localhost",
port=5432,
database="mydatabase",
)
)
connector.save("my-database-block")
Later, you can load it with:
python
from prefect_sqlalchemy import SqlAlchemyConnector
connector = SqlAlchemyConnector.load("my-database-block")
SQLite example
python
from prefect_sqlalchemy import SqlAlchemyConnector, ConnectionComponents, SyncDriver
connector = SqlAlchemyConnector(
connection_info=ConnectionComponents(
driver=SyncDriver.SQLITE_PYSQLITE,
database="example.db",
)
)
connector.save("sqlite-block")
A couple of notes:
- password is handled as a secret field by the block schema.
- DatabaseCredentials appears to be an older/historical name, not a current Prefect 3.x block.
- You'll need the integration installed:
bash
pip install "prefect[sqlalchemy]"
You may also need to register the block types once:
bash
prefect block register -m prefect_sqlalchemy
Relevant docs:
- https://prefecthq.github.io/prefect-sqlalchemy/database/
- https://docs.prefect.io/latest/concepts/blocks/
If you want, I can also show:
- how to create this from a single connection URL, or
- how to use the saved block inside a flow/task.Amir Kamal
05/14/2026, 6:15 AMMarvin
05/14/2026, 6:15 AMMarvin
05/14/2026, 6:17 AMTargetConfigs from prefect-dbt.
Import
python
from prefect_dbt.cli.configs import TargetConfigs
Create and save a generic dbt CLI Target Configs block
python
from prefect_dbt.cli.configs import TargetConfigs
target_configs = TargetConfigs(
type="postgres",
schema_="analytics", # use schema_ in Python; dbt receives "schema"
threads=4,
extras={
"host": "localhost",
"port": 5432,
"user": "myuser",
"password": "mypassword",
"dbname": "mydatabase",
},
)
target_configs.save("my-dbt-target-configs", overwrite=True)
Load it later
python
from prefect_dbt.cli.configs import TargetConfigs
target_configs = TargetConfigs.load("my-dbt-target-configs")
print(target_configs.get_configs())
That get_configs() call returns a dbt-style target config dict, like:
python
{
"type": "postgres",
"schema": "analytics",
"threads": 4,
"host": "localhost",
"port": 5432,
"user": "myuser",
"password": "mypassword",
"dbname": "mydatabase",
}
Database-specific variants also exist, for example:
- SnowflakeTargetConfigs
- BigQueryTargetConfigs
- PostgresTargetConfigs
Example import:
python
from prefect_dbt.cli.configs import PostgresTargetConfigs
A couple of important notes:
- This is part of the prefect-dbt integration, not core Prefect.
- The prefect_dbt.cli module is deprecated in favor of prefect_dbt.core, but TargetConfigs still exists and is usable in Prefect 3.x.
- If you're specifically using dbt CLI Target Configs block in existing code, this is the correct object to create.
You’ll need the integration installed:
bash
pip install prefect-dbt
Helpful links:
- prefect-dbt CLI configs API
- prefect-dbt integration docs
If you want, I can also give you:
- a PostgresTargetConfigs example,
- a SnowflakeTargetConfigs example, or
- how to wire this into a DbtCoreOperation / modern Prefect 3 dbt workflow.Amir Kamal
05/14/2026, 6:22 AMfrom dbt.artifacts.resources.types import NodeType
ModuleNotFoundError: No module named 'dbt.artifacts'Amir Kamal
05/14/2026, 6:23 AMfrom dbt.artifacts.resources.types import NodeType
ModuleNotFoundError: No module named 'dbt.artifacts'Marvin
05/14/2026, 6:23 AMMarvin
05/14/2026, 6:25 AMdbt-core install.
dbt.artifacts.resources.types comes from dbt-core, and prefect-dbt expects a newer dbt version that includes it.
Most likely causes
- dbt-core is not installed
- dbt-core is installed, but it's too old
Recommended fix
bash
pip install "prefect[dbt]"
If you also need a specific adapter, install that too. For example:
bash
pip install "prefect[dbt]" dbt-postgres
or:
bash
pip install "prefect[dbt]" dbt-snowflake
Check what version you have now
bash
pip show dbt-core
You want dbt-core >= 1.7.0.
You can also verify directly:
bash
python -c "from dbt.artifacts.resources.types import NodeType; print(NodeType)"
If that fails, your dbt-core install is the issue.
If you want to force-upgrade cleanly
bash
pip install -U "dbt-core>=1.7.0"
Or, often better, reinstall the relevant set together in a fresh venv:
bash
pip install -U prefect prefect-dbt dbt-core dbt-postgres
One more important note: prefect_dbt.cli is deprecated, so if you're using older examples around CLI config blocks, it may be worth checking whether you can move to the newer prefect_dbt.core pattern.
Docs:
- prefect-dbt integration docs
- dbt-core on PyPI
If you paste your pip show prefect prefect-dbt dbt-core output, I can tell you exactly which package/version mismatch is causing it.Amir Kamal
05/14/2026, 6:27 AMMarvin
05/14/2026, 6:27 AMMarvin
05/14/2026, 6:27 AMdbt-core is really 1.11.9, then the likely issue is not the version itself — it's that you're running Prefect code in a different Python environment than the one where dbt-core 1.11.9 is installed.
Also, dbt-core 1.11 is newer than what prefect-dbt was originally built around, so there may also be a compatibility mismatch depending on your prefect-dbt version.
Most likely possibilities
- python / pip point to different environments
- your worker/runtime env differs from your shell env
- prefect-dbt is old and incompatible with dbt-core 1.11
- another package named dbt is shadowing the real one
Please run these in the exact environment where the error happens:
bash
python -c "import sys; print(sys.executable)"
python -c "import dbt; print(dbt.__file__)"
python -c "from dbt.artifacts.resources.types import NodeType; print(NodeType)"
python -c "import prefect_dbt; print(prefect_dbt.__file__)"
pip show prefect prefect-dbt dbt-core
That will tell us whether:
1. the module is actually importable there, and
2. which installed prefect-dbt version is trying to use it.
I’d also strongly suggest checking your prefect-dbt version specifically. If it’s older, try upgrading it:
bash
pip install -U prefect-dbt
Or install the aligned bundle:
bash
pip install -U "prefect[dbt]"
If this is happening inside a deployment/worker, make sure the worker image or runtime environment has the same packages as your local shell. That mismatch is very common.
If you send me the output of:
bash
pip show prefect prefect-dbt dbt-core
and
bash
python -c "import dbt; print(dbt.__file__)"
I can narrow it down quickly.Amir Kamal
05/14/2026, 6:28 AMAmir Kamal
05/14/2026, 6:28 AMMarvin
05/14/2026, 6:28 AMMarvin
05/14/2026, 6:30 AMprefect-dbt 0.7.16 should be compatible with dbt-core 1.11.9, so this points even more strongly to an environment/import-path problem rather than a simple version mismatch.
Given your error:
python
from dbt.artifacts.resources.types import NodeType
ModuleNotFoundError: No module named 'dbt.artifacts'
and your reported version, the most likely explanations are:
Most likely causes
- prefect-dbt and dbt-core are installed in different environments
- the code is running under a worker/container/venv that does not actually have dbt-core 1.11.9
- a local package/file named dbt.py or dbt/ is shadowing the real dbt-core package
- pip show dbt-core was run in a different interpreter than the one running Prefect
Please run these in the exact runtime where the failure occurs:
bash
python -c "import sys; print(sys.executable)"
python -c "import dbt; print(dbt, dbt.__file__)"
python -c "import importlib.util; print(importlib.util.find_spec('dbt.artifacts'))"
python -c "from dbt.artifacts.resources.types import NodeType; print(NodeType)"
python -c "import prefect_dbt; print(prefect_dbt.__file__)"
pip show prefect prefect-dbt dbt-core
What I expect
- If find_spec('dbt.artifacts') returns None, then the runtime environment does not have the expected dbt package layout.
- If import dbt; print(dbt.__file__) points at something in your project directory, then you have a shadowing problem.
- If sys.executable is not the interpreter you expect, then this is an env mismatch.
A very common fix
Use the same interpreter for install and run:
bash
python -m pip install -U prefect prefect-dbt dbt-core
If you need an adapter too:
bash
python -m pip install -U prefect prefect-dbt dbt-core dbt-postgres
That avoids pip vs python mismatches.
Also worth checking
If this happens in a deployment or worker, inspect the worker image/environment, not just your local shell. Local package versions often differ from the runtime actually executing the flow.
If you want, paste the output of these two commands and I can pinpoint it quickly:
bash
python -c "import dbt; print(dbt, dbt.__file__)"
python -c "import importlib.util; print(importlib.util.find_spec('dbt.artifacts'))"Amir Kamal
05/14/2026, 8:25 AMMarvin
05/14/2026, 8:25 AMMarvin
05/14/2026, 8:25 AMdbt-core package.
Python is importing:
python
/a/flows/dbt/__init__.py
instead of the installed dbt-core package. Since your local dbt package doesn’t contain artifacts, from dbt.artifacts... fails.
Fix
Rename your local dbt package/directory to something else, e.g.:
- dbt_project
- dbt_assets
- my_dbt
- analytics_dbt
Then make sure there are no stale .pyc files / __pycache__ left behind.
For example:
bash
mv /a/flows/dbt /a/flows/dbt_project
find /a/flows -type d -name "__pycache__" -exec rm -rf {} +
Then verify again:
bash
python -c "import dbt; print(dbt, dbt.__file__)"
python -c "import importlib.util; print(importlib.util.find_spec('dbt.artifacts'))"
python -c "from dbt.artifacts.resources.types import NodeType; print(NodeType)"
After the rename, import dbt should point into your site-packages, not /a/flows/dbt/....
So in short: this is not a Prefect bug or a dbt version issue — it’s a Python module name collision.
If you want, I can also help you identify the safest rename pattern for a Prefect project structure.Amir Kamal
05/14/2026, 9:51 AMMarvin
05/14/2026, 9:51 AMMarvin
05/14/2026, 9:51 AMextras field on TargetConfigs, the simplest way is:
- pass a normal Python dict
- make sure all keys are strings
- make sure all values are JSON-serializable
For example:
python
from prefect_dbt.cli.configs import TargetConfigs
import json
extras = {
"host": "localhost",
"port": 5432,
"user": "myuser",
"password": "mypassword",
"dbname": "mydatabase",
"sslmode": "require",
}
# optional validation step
json.dumps(extras)
target_configs = TargetConfigs(
type="postgres",
schema_="analytics",
threads=4,
extras=extras,
)
target_configs.save("my-dbt-target-configs", overwrite=True)
If json.dumps(extras) succeeds, then your extras is valid JSON-compatible data.
Good JSON-compatible value types
- strings
- numbers
- booleans
- None
- lists of the above
- dicts of the above
Bad/non-JSON-safe examples
- datetime objects
- Path objects
- sets
- custom classes
- bytes
Example of converting non-JSON-safe values:
python
from pathlib import Path
extras = {
"path": str(Path("/tmp/my.duckdb")),
"threads": 4,
}
If you want to be strict, you can wrap validation in a helper:
python
import json
def ensure_json_dict(value):
if not isinstance(value, dict):
raise TypeError("extras must be a dict")
try:
json.dumps(value)
except TypeError as exc:
raise ValueError(f"extras must be JSON-serializable: {exc}") from exc
return value
Usage:
python
extras = ensure_json_dict({
"host": "localhost",
"port": 5432,
})
If your goal is specifically to store a JSON string instead of a Python dict, you’d do:
python
json_string = json.dumps(extras)
but for TargetConfigs(extras=...), you usually want a dict, not a JSON string.
Docs:
- prefect-dbt TargetConfigs API
If you want, I can show a concrete example for the exact dbt target type you’re using, like Snowflake, Postgres, BigQuery, or DuckDB.Amir Kamal
05/15/2026, 3:07 AMMarvin
05/15/2026, 3:08 AMMarvin
05/15/2026, 3:08 AMprofiles.yml that “references” a TargetConfigs block.
In the prefect-dbt CLI-style pattern, the usual approach is:
- store the target details in a TargetConfigs block
- load that block in Python
- call get_configs()
- build the dbt profile dictionary yourself
- optionally write it to profiles.yml
Example
python
from pathlib import Path
import yaml
from prefect_dbt.cli.configs import TargetConfigs
target_configs = TargetConfigs.load("my-dbt-target-configs")
profile = {
"my_profile": {
"target": "dev",
"outputs": {
"dev": target_configs.get_configs()
},
}
}
profiles_dir = Path("./.dbt")
profiles_dir.mkdir(parents=True, exist_ok=True)
with open(profiles_dir / "profiles.yml", "w") as f:
yaml.safe_dump(profile, f, sort_keys=False)
That produces a dbt profile shaped like:
python
{
"my_profile": {
"target": "dev",
"outputs": {
"dev": {
"type": "postgres",
"schema": "analytics",
"threads": 4,
"host": "localhost",
"port": 5432,
"user": "myuser",
"password": "mypassword",
"dbname": "mydatabase",
}
}
}
}
A helper function version
python
from pathlib import Path
import yaml
def write_dbt_profile(profile_name, target_name, target_configs_block_name, profiles_dir=".dbt"):
from prefect_dbt.cli.configs import TargetConfigs
target_configs = TargetConfigs.load(target_configs_block_name)
profile = {
profile_name: {
"target": target_name,
"outputs": {
target_name: target_configs.get_configs()
},
}
}
profiles_path = Path(profiles_dir)
profiles_path.mkdir(parents=True, exist_ok=True)
with open(profiles_path / "profiles.yml", "w") as f:
yaml.safe_dump(profile, f, sort_keys=False)
return profiles_path / "profiles.yml"
Usage:
python
path = write_dbt_profile(
profile_name="my_profile",
target_name="dev",
target_configs_block_name="my-dbt-target-configs",
)
print(path)
A couple of important notes
- dbt itself expects a real profiles.yml file or equivalent profile directory.
- TargetConfigs is a Prefect block, but dbt does not know how to “reference” a Prefect block directly inside YAML.
- So the reference happens in Python code, not natively inside profiles.yml.
If you want to keep it all in Prefect, you could also save the whole generated YAML as a Secret, JSON, or String-type block, but usually that’s less useful than just generating the file from TargetConfigs at runtime.
If you want, I can show:
- how to do this in a flow/task,
- how to write multiple outputs (`dev`/`prod`) into one profile, or
- how to use DbtCoreOperation with the generated profile.Amir Kamal
05/15/2026, 3:10 AMMarvin
05/15/2026, 3:10 AMMarvin
05/15/2026, 3:11 AMDbtCliProfile.
Import paths
python
from prefect_dbt.cli.credentials import DbtCliProfile
from prefect_dbt.cli.configs import TargetConfigs, GlobalConfigs
Basic example: create a dbt CLI Profile block programmatically
python
from prefect_dbt.cli.credentials import DbtCliProfile
from prefect_dbt.cli.configs import TargetConfigs, GlobalConfigs
target_configs = TargetConfigs(
type="postgres",
schema_="analytics",
threads=4,
extras={
"host": "localhost",
"port": 5432,
"user": "myuser",
"password": "mypassword",
"dbname": "mydatabase",
},
)
global_configs = GlobalConfigs(
use_colors=False,
send_anonymous_usage_stats=False,
)
profile = DbtCliProfile(
name="my_dbt_profile", # profile name in profiles.yml
target="dev", # output name
target_configs=target_configs,
global_configs=global_configs,
)
profile.save("my-dbt-cli-profile", overwrite=True)
Load it later
python
from prefect_dbt.cli.credentials import DbtCliProfile
profile = DbtCliProfile.load("my-dbt-cli-profile")
Generate the dbt profile dict from it
python
profile_dict = profile.get_profile()
print(profile_dict)
That will produce something shaped like:
python
{
"config": {
"use_colors": False,
"send_anonymous_usage_stats": False,
},
"my_dbt_profile": {
"target": "dev",
"outputs": {
"dev": {
"type": "postgres",
"schema": "analytics",
"threads": 4,
"host": "localhost",
"port": 5432,
"user": "myuser",
"password": "mypassword",
"dbname": "mydatabase",
}
}
}
}
A few important notes
- DbtCliProfile is the block behind the UI label “dbt CLI Profile”.
- It contains a target_configs object, so yes, this is how you reference the target config programmatically.
- prefect_dbt.cli is deprecated, but this block still exists and works in current Prefect 3.x setups.
If you already have a saved TargetConfigs block and want to reuse it, you can do:
python
from prefect_dbt.cli.credentials import DbtCliProfile
from prefect_dbt.cli.configs import TargetConfigs
target_configs = TargetConfigs.load("my-dbt-target-configs")
profile = DbtCliProfile(
name="my_dbt_profile",
target="dev",
target_configs=target_configs,
)
profile.save("my-dbt-cli-profile", overwrite=True)
Docs:
- prefect-dbt integration docs
- `DbtCliProfile` API
If you want, I can give you the exact snippet for:
- Postgres
- Snowflake
- BigQuery
- or how to write the saved DbtCliProfile back out to a profiles.yml file.Amir Kamal
05/15/2026, 5:14 AMMarvin
05/15/2026, 5:14 AMMarvin
05/15/2026, 5:14 AMprefect.blocks.system.Secret.
Example
python
from prefect.blocks.system import Secret
secret = Secret(value="super-secret-value")
secret.save("my-secret", overwrite=True)
Load it later
python
from prefect.blocks.system import Secret
secret = Secret.load("my-secret")
value = secret.get()
print(value)
If you want to use it for something like a dbt password:
python
from prefect.blocks.system import Secret
db_password = Secret(value="mypassword")
db_password.save("dbt-password", overwrite=True)
Then later:
python
from prefect.blocks.system import Secret
password = Secret.load("dbt-password").get()
A couple notes
- save("my-secret") is the block document name you’ll see in the UI.
- Use .get() to retrieve the underlying secret value.
- The value is masked in the UI.
Docs:
- Prefect blocks docs
- system blocks API
If you want, I can also show how to:
- store a JSON payload as a secret,
- use a secret inside a DbtCliProfile,
- or create the same block via CLI/UI.