Original release notes
[!WARNING] Self-hosted deployments using the bundled Weaviate must complete a manual, staged upgrade before starting 1.17.1. The bundled Weaviate server moves from
1.27.0to1.39.2- 12 minor versions - and skipping minors is unsupported. Pulling and restarting can silently and permanently break vector search. See Upgrade Guide below. Fresh deployments, external Weaviate, and other vector stores are unaffected.
New Features
Dataset-Scoped Knowledge Base API Keys
- Knowledge base service-API keys were scoped to the whole workspace: one key could read and write every knowledge base in the tenant, so giving an integration access to a single knowledge base meant giving it access to all of them. Keys can now be bound to specific knowledge bases from the knowledge base's API access panel, with a workspace / this-knowledge-base scope selector at creation time. A bound key returns
403for any other dataset - both documents and retrieval - and for endpoints that carry no dataset ID, such as list-all. Existing keys are unbound and keep their workspace-wide behavior, so nothing changes when you upgrade. (#37569)
Keyboard Movement for Workflow Nodes and Comments
- The workflow canvas required a mouse to reposition anything. Nodes, multi-node selections, comment markers, and draft comments can now be moved with the arrow keys - hold Shift for larger steps - including Note, Iteration, and Loop nodes. Continuous movement is committed on key release or blur, so it produces one undo entry rather than one per keypress, and read-only mode, container boundaries, and collaboration updates are all still respected. (#41967)
Marketplace Creator Profiles and Homepage Redesign
- Plugin authors now have public profile pages at
/marketplace/creator/, listing their creations with a publisher sidebar, reachable from a new Creator Center entry in the sidebar help menu. The marketplace homepage was rebuilt around a hero, a banner carousel, sticky search, catalog tabs, and tag/language filters, with a stacked-and-swipeable mobile layout. Bundles are no longer mixed into plugin categories. (#41538)
Configurable Markdown Form Field Name Length
- The Markdown form field-name limit was hard-coded at 128 characters, with no way to accommodate longer generated field names. It is now configurable through
MARKDOWN_FORM_FIELD_NAME_MAX_LENGTH(Docker) orNEXT_PUBLIC_MARKDOWN_FORM_FIELD_NAME_MAX_LENGTH(direct Web deployments), defaulting to the previous 128. Character validation and prototype-pollution protections are unchanged. (#41697)
---
Bug Fixes
Knowledge Base
This release fixes a cluster of extraction bugs that changed document content without reporting an error. Re-import affected documents after upgrading; indexed text is not retroactively repaired.
- CSV cells were passed through pandas type inference before indexing. Leading-zero codes became floats (
00123123.0), empty cells became the literal stringnan, and cells containingNAorNULLbecame missing values. The extractor now reads everything as text and disables missing-value inference; an explicitcsv_argsstill overrides this for callers that want typed parsing. (#41922) - Notion table rows lost or gained columns. Each rich-text segment inside a cell was emitted as its own Markdown column, so any cell with mixed formatting - bold, links, mentions - produced extra columns and corrupted the table, while an empty cell was skipped entirely and shifted the rest of the row left. Cells are now emitted one-per-column with their segments concatenated. (#41993)
- Notion database properties were truncated at the first formatting change.
rich_textandtitleproperties read only their first segment, so a title ofHello worldwithworldin bold was indexed as justHello. All segments are now joined. (#42050) .xlscells containing double quotes corrupted the row. The extractor emits"column":"value"pairs; the.xlsxpath escaped embedded quotes but the legacy.xlspath interpolated them raw, sohe said "hi"became"note":"he said "hi"". Both engines now behave the same for the same content. (#42049)- Any PDF loaded from a URL crashed with a bare
AssertionError. After tenant context was added to the PDF extractor, the code path used byload_from_url- including the built-in web scraper whenever a target returnsContent-Type: application/pdf- asserted on an upload record that URL loads never have. Tenant context is now optional, image extraction is skipped when it is absent, and text extraction works again. (#41950) - The built-in web scraper returned Python data structures instead of page text.
readabilipyhands backplain_textas a list of dicts, which was interpolated straight into the output template, so every scraped page came back as `[{'text': '
...
'}, ...]` - dict syntax, quotes, and HTML tags included. The items are now flattened into readable text. (#41954)
- Partial segment updates wiped attachments. A segment update that omitted
attachment_idswas treated as "replace with nothing", deleting the segment's attachment bindings and multimodal vectors. Attachments are now left alone unlessattachment_idsis explicitly provided; passing[]still clears them. (#41777) - Documents with invalid Markdown image links could stall the indexing queue. Relative, protocol-relative,
data:,ftp:, and malformed image targets were all handed to the remote image fetcher and entered its SSRF retry loop, so a single document with many bad references could hold an indexing worker long enough to back up everything behind it. Non-fetchable targets are now validated and skipped. (#41343) - Deleting content left orphaned files in object storage. Segment deletion, multimodal re-indexing, and batch document deletion each removed the database rows but left the physical attachment objects behind. All three paths now delete the underlying objects after the database commit, with an orphan check so attachments shared by other segments survive. (#41400, #41999, #41256)
- Text file previews were misreported as binary. When the preview byte limit cut through a multi-byte UTF-8 character, strict decoding failed and the whole file was classified as binary - reproducible on a default preview with a single non-ASCII character at the 256 KiB boundary. Previews now keep the longest complete UTF-8 prefix; files with genuinely invalid encoding are still reported as binary. (#41761)
Model Providers
- Upgrades from pre-1.15 no longer leave models unusable, and no longer need a manual command. Installations older than 1.15 still carry legacy model type values (
text-generation,embeddings,reranking) in their provider tables, which makes model-related API requests fail and prevents affected models from loading. Both 1.16.1 and 1.17.0 shipped this as a separateflask data-migrate legacy-model-typesstep that had to be run by hand. It now runs as part offlask db upgrade: legacy values are canonicalized tollm/text-embedding/rerank, legacy-versus-canonical row collisions are resolved deterministically while preserving credential references, and the provider cache namespace is rotated so stale cached credentials cannot shadow the migrated rows. (#41326, fixes #41294) - The built-in file upload data source asked for authorization it does not need. When creating a RAG Pipeline knowledge base, local file upload showed "Please authorize first" and the creation checklist flagged it, because providers that declare no credentials schema never have a stored-credential row and were therefore always reported as unauthorized. Credential-free providers are now marked authorized directly. (#39772)
- Provider-scoped credential validation rules are now applied, and missing tool credentials are surfaced instead of failing opaquely. (#41659, #41726)
Workflow & Triggers
- Human Input forms could finish a workflow while leaving it looking stuck. Since the HITL callback migration in 1.17.0, submitting a form left its approval buttons on screen and the published Web App input blocked, because the engine emitted a generic node-success event without the form-filled or timeout events the response pipeline expects. Those events are now reconstructed, preserving submitted file values, original timeout deadlines, and execution metadata. (#42082)
- Human Input could not be placed inside Iteration or Loop nodes, even though 1.17.0 shipped the runtime support for it - two stale editor guards still blocked selecting, connecting, and pasting the node inside a container. (#40061)
- The Human Input timeout edge could fire the wrong branch. The editor writes the timeout edge as
__timeout, but the backend compared against__timeout__, so at runtime a timeout could take a user-action branch instead of the timeout branch the author drew. (#40746) - A second Human Input pause in the same run could become unresumable. If object storage rejected deleting the previous pause snapshot, the exception aborted the transaction - the run was already persisted as
PAUSED, but its only pause row was the previous, already-resumed one, so the next submission failed withCannot resume an already resumed pause. Snapshot cleanup is now best-effort, with the orphaned object key logged for later cleanup, so the run's durable state stays correct. (#41581) - Workflow-as-Tool only exposed the first End node's outputs. Output declarations are now collected from every End node, with the source node listed for each, one warning per output affected by a duplicate or reserved name, and a fallback to the published schema when live draft metadata is unavailable. (#41517)
- Loop Boolean break conditions never matched. New conditions stored
"true"/"false"as strings rather than booleans. Values are now stored and kept as real booleans, and legacy string values are normalized when rendered. (#41186) - Trigger-entry workflows could still be invoked manually from the Web App, Service API, OpenAPI, and MCP
tools/call- creating workflow runs that could never work. These are now rejected before a run or log is created, with a shared business code across HTTP and MCP JSON-RPC. Real trigger execution, read-only endpoints, and running a historical Start version by ID are unaffected. (#41519) - A single bad LLM node took down the whole editor. A workflow whose LLM node had
model_selectorpersisted asnullrather than omitted crashed Workflow Studio's per-node checklist on load and tripped the page-level error boundary, making the entire canvas unusable rather than flagging one node. (#41707) - Workflows containing legacy Agent nodes could not be published once Agent V2 was enabled, because publish validation could not resolve the legacy validator. They publish again, while legacy Agent nodes stay hidden from the node picker. (#41368)
- Creating a tool from a workflow used the previously published version. The current workflow is now published first - matching what the update path already did - and provider creation stops if that publish fails, instead of silently binding to a stale version. (#41528)
- Undoing the deletion of a webhook trigger node changed its URL. (#42069)
- Document create and update could report "One or more files not found." on MySQL even though the upload had committed. Under MySQL's default
REPEATABLE READ, the request session's read snapshot was pinned before the upload happened in a separate session, so the just-written rows were invisible. All four affected endpoints - create-by-text, create-by-file, update-by-text, update-by-file - now refresh the snapshot before the lookup. PostgreSQL was never affected. (#41840) - Large workflow graphs broke the collaboration socket.
sync_requestpayloads exceeded Engine.IO's 1 MiB default, so the frame was rejected and the editor reconnect-looped. The ceiling is now configurable throughWEBSOCKET_MAX_HTTP_BUFFER_SIZE, default 10 MiB. (#41347) - The Access Point page no longer shows "no published version" guidance when the published-workflow request simply failed, and no longer retries requests that returned
403. (#41572)
Agent & Chat
- Chatflow Agent V2 forgot everything between turns. Sessions are now keyed by
conversation_id, so memory persists across a conversation. A follow-up fixed the related case where publishing a new Agent roster version mid-conversation paired a new configuration with the previous participant and failed generation validation - existing conversations now stay pinned to the version they started on, and only new conversations pick up the current one. (#41871, #42105) - Replies from reasoning models rendered entirely as "thinking". Models such as GLM-5.3 wrap chain-of-thought in
tags, and a tool call frequently interrupts generation beforeis emitted, leaving the answer nested inside a still-open tag. The dangling tag is now closed when a tool log interrupts the stream, when a newstarts after real content, and at stream end - plus the same repair in the Markdown preprocessor so already-stored output renders correctly. (#41764) - Images uploaded to an Agent App were turned into shell download instructions rather than being shown to the model. Vision-capable models now receive them as native multimodal content, detected from the selected credential-bound model schema. The download fallback is preserved for non-image files and for models without vision support, and image URLs and Base64 payloads are redacted from agent backend logs. (#41685)
- Suggested questions could take minutes, or hang. With no dedicated suggested-question model configured, the endpoint fell back to the workspace default - inheriting expensive settings such as
reasoning_effort=high, a 2,560-token output allowance, and the global 600-second plugin timeout, so the browser gave up after 100 seconds while the backend kept working. Output is now capped at 256 tokens, thinking is disabled or set to the lowest supported effort, and a request-scoped 30-second timeout applies. One reported case went from 113-344 seconds to under 3 seconds; an unavailable default model now returns an empty list immediately instead of failing. (#41705)

