Skip to content

Commit 3007308

Browse files
authored
Merge branch 'release-1.12.0' into fix/background-job-timeout-ignored
2 parents 6e3cc0c + 3e5692b commit 3007308

54 files changed

Lines changed: 1773 additions & 186 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.secrets.baseline

Lines changed: 73 additions & 73 deletions
Large diffs are not rendered by default.

docs/docs/Develop/configuration-cli.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ Use this mode to previews the changes that would be made to the database schema
191191
:::warning
192192
`langflow migration --fix` is a destructive operation that can delete data.
193193
Always run `langflow migration` first to preview the changes.
194+
For more information, see [Database migrations](./database-migrations).
194195
:::
195196

196197
<Tabs groupId="Invocation">

docs/docs/Develop/configuration-custom-database.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ Since each Langflow instance runs in its own container on the Docker network, us
202202

203203
## See also
204204

205+
* [Database migrations](./database-migrations)
205206
* [Langflow database guide for enterprise DBAs](/enterprise-database-guide)
206207
* [Memory management options](/memory)
207208
* [Logs](/logging)
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
---
2+
title: Database migrations
3+
slug: /database-migrations
4+
---
5+
6+
Langflow stores application data such as flows, users, and API keys in a SQL database.
7+
8+
When you upgrade Langflow or connect to a new empty database, Langflow must keep the database schema aligned with the application models.
9+
10+
By default, the Langflow database uses [SQLite](https://www.sqlite.org/docs.html), and uses [Alembic](https://alembic.sqlalchemy.org/) for SQL database migrations.
11+
12+
This page explains when migrations run and how to run and repair migrations safely.
13+
14+
## Default migrations behavior and triggers
15+
16+
Most Langflow users never need to run a database migration.
17+
When you start Langflow, or restart a container after upgrading the Langflow image, pending Alembic migrations run as part of database initialization.
18+
19+
Langflow includes [Alembic revision scripts](https://github.com/langflow-ai/langflow/tree/main/src/backend/base/langflow/alembic) with the package.
20+
On startup, Langflow connects to the database at [`LANGFLOW_DATABASE_URL`](/memory#configure-external-memory) or the default `langflow.db` file, ensures the required tables exist, checks the database schema against the current models, and then applies any pending Alembic upgrades to bring the schema to its `head` revision.
21+
22+
Alembic records the applied revision in the `alembic_version` table.
23+
24+
Other events that trigger Alembic checks are a first Langflow startup against a new SQLite file or empty PostgreSQL database, upgrading to a Langflow version that includes new Alembic revisions, or pointing [`LANGFLOW_DATABASE_URL`](/memory#configure-external-memory) at an empty database.
25+
26+
## Upgrade Langflow safely
27+
28+
To upgrade Langflow or change the database URL in a deployment that already has data, you may need a database migration.
29+
To migrate your database, do the following:
30+
31+
1. Stop Langflow.
32+
2. Back up the database.
33+
34+
If you're using SQLite, copy the `langflow.db` file.
35+
The default path depends on your install method and whether `LANGFLOW_SAVE_DB_IN_CONFIG_DIR` is set.
36+
For more information, see [Memory management options](/memory#storage-options-and-paths).
37+
38+
If you're using PostgreSQL, make a logical backup with `pg_dump`, or use your database provider's snapshot.
39+
For more information, see [enterprise backup guidance](/enterprise-database-guide).
40+
41+
3. Export any flows you want to save as JSON. For more information, see [Import and export flows](/concepts-flows-import).
42+
4. Upgrade the Langflow package or container image to the latest version, keeping the same [`LANGFLOW_DATABASE_URL`](/memory#configure-external-memory) or the same SQLite path.
43+
44+
```bash
45+
uv pip install langflow -U
46+
```
47+
48+
5. Start a **single** Langflow instance, so database migrations run without concurrent database writes.
49+
6. Confirm that startup succeeds.
50+
7. If startup reports a schema mismatch, run `langflow migration` to inspect the problem and restore from backup if needed.
51+
For more information, see [`langflow migration` CLI](/configuration-cli#langflow-migration).
52+
53+
## Switch from SQLite to PostgreSQL
54+
55+
Changing `LANGFLOW_DATABASE_URL` from SQLite to PostgreSQL does **not** copy existing SQLite data into PostgreSQL.
56+
Langflow initializes and migrates the new database schema, and your previous SQLite file remains where it was.
57+
58+
There is no built-in SQLite-to-PostgreSQL data migrator.
59+
Langflow creates a new PostgreSQL schema, and then you can restore application data you saved.
60+
61+
To migrate your flows while switching from SQLite to PostgreSQL, do the following:
62+
63+
1. [Export flows](/concepts-flows-import), and note any [global variables](/configuration-global-variables) or credentials.
64+
2. Provision PostgreSQL 15+ and set `LANGFLOW_DATABASE_URL` as described in [Configure an external PostgreSQL database](/configuration-custom-database).
65+
3. If required, install PostgreSQL driver extras, for example `uv pip install "langflow[postgresql]"`.
66+
4. Start Langflow. The new PostgreSQL schema is created.
67+
5. Import the exported flows and recreate secrets or variables as needed.
68+
69+
## Migration logging
70+
71+
Alembic output is written to a log file by default at `alembic/alembic.log` under the Langflow config directory (`LANGFLOW_CONFIG_DIR`).
72+
Relative `LANGFLOW_ALEMBIC_LOG_FILE` values are also resolved against that config directory.
73+
In read-only or hardened containers, that path may not be writable, and Langflow will fall back to `stdout` and continue the migration.
74+
75+
## Migration environment variables
76+
77+
| Variable | Purpose |
78+
|----------|---------|
79+
| `LANGFLOW_ALEMBIC_LOG_TO_STDOUT` | Set to `true` to send Alembic migration output to `stdout`. |
80+
| `LANGFLOW_ALEMBIC_LOG_FILE` | Absolute or relative path for the Alembic log file when not logging to `stdout`. Relative paths resolve under the Langflow config directory. |
81+
| `LANGFLOW_MIGRATION_LOCK_TIMEOUT_S` | Seconds to wait for the PostgreSQL migration advisory lock. Default: `300`. |
82+
| `LANGFLOW_MIGRATION_LOCK_NAMESPACE` | Optional namespace for the Alembic PostgreSQL advisory lock. The default lock key coordinates instances that share a database. Set this variable to isolate different Langflow deployments that share one PostgreSQL server. Use the same value on every instance in that deployment. |
83+
84+
## Troubleshooting
85+
86+
For troubleshooting database migrations, see [Langflow upgrade issues](/troubleshoot#langflow-upgrade-issues).
87+
88+
## See also
89+
90+
* [Configure an external PostgreSQL database](/configuration-custom-database)
91+
* [Langflow database guide for enterprise DBAs](/enterprise-database-guide)
92+
* [Memory management options](/memory)
93+
* [`langflow migration` CLI](/configuration-cli#langflow-migration)
94+
* [Troubleshoot Langflow](/troubleshoot)
95+
* [Deploy Langflow on Docker](/deployment-docker)

docs/docs/Develop/enterprise-database-guide.mdx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ For more information, see [Configure an external PostgreSQL database](/configura
119119
3. Run `langflow migration --fix` to run the migration and permanently apply the changes.
120120

121121
This is a destructive operation that can delete data.
122-
For more information, see [`langflow migration`](/configuration-cli#langflow-migration).
122+
For more information, see [Database migrations](./database-migrations).
123123

124124
6. To verify the configuration, create any flow using the Langflow visual editor or API, and then query your database to confirm the tables and activity are recorded there. The content of the flow doesn't matter; you only need to confirm that the flow is stored in your PostgreSQL database.
125125
You can query the database in two ways:
@@ -287,5 +287,6 @@ For example, use `pg_stat_activity` to monitor connection counts and contention.
287287
## See also
288288

289289
* [Configure an external PostgreSQL database](/configuration-custom-database)
290+
* [Database migrations](./database-migrations)
290291
* [Langflow architecture on Kubernetes](/deployment-architecture)
291292
* [Deploy the Langflow production environment on Kubernetes](/deployment-kubernetes-prod)

docs/docs/Develop/memory.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,8 @@ For more information and examples, see [**Message History** component](/message-
206206

207207
## See also
208208

209+
* [Database migrations](./database-migrations)
210+
* [Configure an external PostgreSQL database](/configuration-custom-database)
209211
* [Langflow file management](/concepts-file-management)
210212
* [Langflow logs](/logging)
211213
* [Langflow environment variables](/environment-variables)

docs/docs/Support/troubleshooting.mdx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -498,12 +498,19 @@ The following error can occur during Langflow upgrades when the database schema
498498
There's a mismatch between the models and the database.
499499
```
500500
501-
To resolve this error, run the migration fix command:
501+
Back up your database first, and then run the migration fix command:
502502
503503
```bash
504504
uv run langflow migration --fix
505505
```
506506
507+
:::warning
508+
`langflow migration --fix` is destructive.
509+
Use a dedicated database for Langflow application data.
510+
Repair mode repeatedly downgrades and re-applies Langflow's schema revisions, which can delete Langflow data, and it might fail to converge when non-Langflow tables such as `langchain_pg_*` vector store tables share the same database.
511+
For more information, see [Database migrations](./database-migrations).
512+
:::
513+
507514
If the migration fix doesn't resolve the issue, clear the cache by deleting the contents of your Langflow cache folder.
508515
The filepath depends on your operating system, installation type, and configuration options.
509516
For more information and default filepaths, see [Memory management options](/memory).

docs/sidebars.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,11 @@ module.exports = {
154154
label: "Use Session IDs"
155155
},
156156
"Develop/configuration-custom-database",
157+
{
158+
type: "doc",
159+
id: "Develop/database-migrations",
160+
label: "Database migrations"
161+
},
157162
{
158163
type: "doc",
159164
id: "Develop/enterprise-database-guide",

src/backend/base/langflow/agentic/api/router.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
get_enabled_providers_for_user,
3838
list_installed_tool_calling_models,
3939
)
40-
from langflow.api.utils.core import CurrentActiveUser, DbSession
40+
from langflow.api.utils.core import CurrentActiveUser, DbSession, release_db_transaction
4141

4242
router = APIRouter(prefix="/agentic", tags=["Agentic"])
4343

@@ -175,6 +175,10 @@ async def execute_named_flow(
175175
"""
176176
ctx = await _resolve_assistant_context(request, current_user.id, session)
177177

178+
# The flow run below can wait on a model for minutes; don't hold the
179+
# request transaction (and its pooled connection) open across it (#14445).
180+
await release_db_transaction(session)
181+
178182
global_vars = dict(ctx.global_vars)
179183
if request.component_id:
180184
global_vars["COMPONENT_ID"] = request.component_id
@@ -294,6 +298,10 @@ async def assist(
294298

295299
logger.info(f"Executing {LANGFLOW_ASSISTANT_FLOW} with {ctx.provider}/{ctx.model_name}")
296300

301+
# The assistant run below can wait on a model for minutes; don't hold the
302+
# request transaction (and its pooled connection) open across it (#14445).
303+
await release_db_transaction(session)
304+
297305
return await execute_flow_with_validation(
298306
flow_filename=LANGFLOW_ASSISTANT_FLOW,
299307
input_value=request.input_value or "",
@@ -318,6 +326,11 @@ async def assist_stream(
318326
await _validate_flow_access(request.flow_id, current_user.id, session)
319327
ctx = await _resolve_assistant_context(request, current_user.id, session)
320328

329+
# Dependency teardown only runs after the SSE stream finishes, so without
330+
# this commit the request transaction (and its pooled connection) would
331+
# stay open for the assistant's whole streaming run (#14445).
332+
await release_db_transaction(session)
333+
321334
return StreamingResponse(
322335
execute_flow_with_validation_streaming(
323336
flow_filename=LANGFLOW_ASSISTANT_FLOW,

src/backend/base/langflow/agentic/utils/assistant_runner.py

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,12 @@
2121
from langflow.agentic.api.schemas import AssistantRequest
2222
from langflow.agentic.services.assistant_service import execute_flow_with_validation_streaming
2323
from langflow.agentic.services.flow_types import LANGFLOW_ASSISTANT_FLOW
24-
from langflow.api.v1.flows import _new_flow, _save_flow_to_fs
24+
from langflow.api.utils.core import release_db_transaction
25+
from langflow.api.v1.flows import _new_flow, _save_flow_to_fs, _validate_catalog_policy_for_write
2526
from langflow.initial_setup.setup import get_or_create_default_folder
2627
from langflow.services.database.models.flow.guards import ensure_flow_unlocked, lock_flow_for_update
2728
from langflow.services.database.models.flow.model import Flow, FlowCreate
28-
from langflow.services.deps import get_storage_service
29+
from langflow.services.deps import get_catalog_policy_service, get_storage_service
2930

3031
if TYPE_CHECKING:
3132
from sqlmodel.ext.asyncio.session import AsyncSession
@@ -156,7 +157,8 @@ async def _consume_stream(
156157
data = event.get("data") or {}
157158
result_text = data.get("result")
158159
working = get_working_flow()
159-
if isinstance(working, dict) and working.get("data", {}).get("nodes"):
160+
working_data = working.get("data") if isinstance(working, dict) else None
161+
if isinstance(working_data, dict) and isinstance(working_data.get("nodes"), list):
160162
working_snapshot = copy.deepcopy(working)
161163
elif event_type == "error":
162164
error_text = event.get("message")
@@ -195,6 +197,12 @@ async def run_assistant_and_persist(
195197
)
196198
ctx = await _resolve_assistant_context(request, user_id, session)
197199

200+
# The agent loop below can run for minutes; end the read transaction now
201+
# so it doesn't pin a pooled connection (Postgres: idle-in-transaction)
202+
# for the whole run (#14445). Persistence re-reads under a fresh short
203+
# transaction (the FOR UPDATE below), so the lock ordering is preserved.
204+
await release_db_transaction(session)
205+
198206
stream = execute_flow_with_validation_streaming(
199207
flow_filename=LANGFLOW_ASSISTANT_FLOW,
200208
input_value=instruction,
@@ -220,6 +228,19 @@ async def run_assistant_and_persist(
220228
# each to the working flow here or the text edit is dropped (Bug #13641).
221229
for edit in field_edits:
222230
_apply_field_edit(flow_data, edit)
231+
try:
232+
_validate_catalog_policy_for_write(
233+
flow_data,
234+
snapshot=get_catalog_policy_service().snapshot,
235+
)
236+
except HTTPException:
237+
if created_new:
238+
# The assistant needs a committed flow id while it runs. Do not
239+
# leave that provisional row behind when its generated graph is
240+
# rejected before the caller ever receives the id or link.
241+
await session.delete(flow)
242+
await session.commit()
243+
raise
223244
flow.data = flow_data
224245
if created_new and canvas.name:
225246
flow.name = canvas.name

0 commit comments

Comments
 (0)