Bug summary
When running Prefect Server v3 with PostgreSQL and a custom search_path, we are consistently encountering foreign key violations where task_run.flow_run_id references a non‑existent record in flow_run.
This suggests that, under certain conditions, the server may be inserting task_run records using a database connection whose search_path does not resolve the same schema used when the corresponding flow_run was created. As a result, the task_run insert fails due to an unresolved foreign key reference.
This issue appears only after configuring a non‑default schema via search_path and does not occur when using the default public schema.
Minimal Reproducible Example
Environment
- Prefect Server v3
- PostgreSQL
- Async engine (postgresql+asyncpg)
- Custom schema (e.g. app_prefect)
- search_path configured via Prefect settings / environment variables
Server configuration
export PREFECT_DATABASE_CONNECTION_URL="postgresql+asyncpg://user:password@host:5432/prefect"
export PREFECT_DATABASE_SQLALCHEMY_CONNECT_ARGS='{
"search_path": "app_prefect",
"application_name": "prefect-server"
}'
export PREFECT_DATABASE_MIGRATE_ON_START=true
Reproduction steps
Start Prefect Server with the configuration above.
Run a flow with at least one task.
Observe server logs during execution.
Stack Trace
sqlalchemy.dialects.postgresql.asyncpg.AsyncAdapt_asyncpg_dbapi.IntegrityError:
<class 'asyncpg.exceptions.ForeignKeyViolationError'>:
insert or update on table "task_run" violates foreign key constraint
"fk_task_run__flow_run_id__flow_run"
DETAIL:
Key (flow_run_id)=(cee30874-353e-495a-beaf-521d468f2cb6)
is not present in table "flow_run".
Full trace excerpt:
File ".../prefect/server/services/task_run_recorder.py", line 379, in _record_bulk_task_run_events
await session.execute(upsert_statement)
sqlalchemy.exc.IntegrityError:
(sqlalchemy.dialects.postgresql.asyncpg.IntegrityError)
<class 'asyncpg.exceptions.ForeignKeyViolationError'>:
insert or update on table "task_run" violates foreign key constraint
"fk_task_run__flow_run_id__flow_run"
Version info
Version: 3.7.1
API version: 0.8.4
Python version: 3.12.12
Git commit: e914068e
Built: Sat, May 16, 2026 02:20 AM
OS/Arch: linux/x86_64
Profile: local
Server type: server
Pydantic version: 2.13.4
Additional context
Additional Details
- Both flow_run and task_run tables exist and have correct foreign key definitions.
- The issue only occurs when a custom schema is used via search_path.
- When reverting to the default public schema, the problem disappears.
- This raises the possibility that:
- Different async connections may not consistently apply the same search_path, or
- Some internal services may be executing with a different or default search_path, causing schema resolution mismatch.
- The error originates entirely from Prefect server internals (no user code interaction with the database).
Hypothesis
It appears that, when using a custom search_path, Prefect may sometimes attempt to insert task_run records before (or independently of) resolving the corresponding flow_run in the same schema, leading to foreign key violations.
This may indicate that search_path handling is not fully consistent across all async database sessions used by the server.
Bug summary
When running Prefect Server v3 with PostgreSQL and a custom search_path, we are consistently encountering foreign key violations where task_run.flow_run_id references a non‑existent record in flow_run.
This suggests that, under certain conditions, the server may be inserting task_run records using a database connection whose search_path does not resolve the same schema used when the corresponding flow_run was created. As a result, the task_run insert fails due to an unresolved foreign key reference.
This issue appears only after configuring a non‑default schema via search_path and does not occur when using the default public schema.
Minimal Reproducible Example
Environment
Server configuration
Reproduction steps
Start Prefect Server with the configuration above.
Run a flow with at least one task.
Observe server logs during execution.
Stack Trace
Full trace excerpt:
Version info
Additional context
Additional Details
Hypothesis
It appears that, when using a custom search_path, Prefect may sometimes attempt to insert task_run records before (or independently of) resolving the corresponding flow_run in the same schema, leading to foreign key violations.
This may indicate that search_path handling is not fully consistent across all async database sessions used by the server.