Release v6.33.0 (2026-06-04)
Published 2026-06-04 14:28:57Z
Important
Data Model: Due to a wrong internal search.facet setting, masks will be cleaned up automatically when opening the data model. You will see a prompt where you need to click Ok. No other actions needed.
This release forces a blocking re-index. Make sure to plan enough time for this update, as your users will not be able to access the database while the re-index is running. Only
/inspect/is available while the re-index runs. The re-index clears straydate_rangeaggregation markers from existing objects (see /api/search under Fixed), and repairs base-type objects (messages, collections, pools, groups) whose long localized free text previously failed to index and dropped out of search (see Indexer under Fixed). [609ada17e]Custom produce config: if your instance uses a custom produce config, re-check INDD handling after the update. INDD files are now produced in the
officeclass instead ofimage; the migration movesinddaccordingly, but INDD only produces versions where yourofficeclass haspdfversions to ride on. With noofficeclass, or nopdfversion, INDD files upload but produce nothing (no thumbnail, preview or pages). Independently of the produce config, INDD files that were already uploaded keep their old single image until you re-produce them — see /eas, produce config under Improved for how to do that from/inspect/files. [56cfeb641]OAuth login redirects: a cross-origin destination reached after OAuth login must now be allow-listed via
fylr.services.webapp.loginAllowRedirects, or the redirect is refused. Same-origin destinations (a local path, or one matchingfylr.externalURL) keep working without configuration. The default config bakes inhttps://*.web.fylr.dev,http://localhost:*andhttps://localhost:*; if your frontend finishes login on another host, add it to the list. See OAuth login under Fixed. [545536f31]
Server
New
/inspect: New
SQL Queryutility under/inspect/sqlquery/that lets an inspect-authenticated user run read-onlySELECTqueries against the configured database, with paging, ordering and a per-browser query history. The endpoint also acceptsapplication/json, so it can be driven from apitests. Because queries run with the privileges of the configured fylr database user, it is gated behind a new config flagfylr.debug.inspectEnableSqlQuery(off by default). Enable it only on developer / debug instances, and make sure the fylr DB user is not a Postgres superuser. [96ceacb61]/api/search:
daterangevalues anddate_rangeaggregation bucket boundaries can now carry an explicit timezone offset on partial-date precisions (year, year-month, date) — e.g.2025+01:00,2025-12+01:00,2025-12-31+01:00. ISO 8601 itself does not allow timezone designators on partial dates; this is a fylr-specific extension. Untagged values continue to be interpreted as UTC, so existing data and the webfrontend are unaffected. Also removes the long-deadformatparameter fromdate_rangeaggregation requests — it has been silently ignored since 2022, and unknown keys are ignored, so clients that still send it are unaffected. [eb3c57460]/inspect/objects: The per-objecttype list at
/inspect/objects/<table>/now answersAccept: application/jsonwith pagination meta and thesystem_object_idson the page, so monitoring can alert on objects stuck in "not found READ" without scraping the inspect HTML. The single-object view at/inspect/objects/<id>/gains?datamodel=<id>to render an object against any datamodel version (current, historic or uncommitted HEAD) and?latest_linked=0|1to choose whether linked objects load at their stored version or the current latest. [3c5600aaa] [003a585cb]OAuth2 /
/api/oauth2/token: The client-credentials grant now logs in as an anonymous user. A request withgrant_type=client_credentialsresolves (or creates) the anonymous user bound to the browser client and returns an access token for it, so a public frontend can obtain an anonymous session without any user credentials. This requires guest access to be enabled in the base config (login.guest); with guest access off the request is rejected and a warning is written to the fylr log. Anonymous token logins are recorded asUSER_LOGIN/USER_LOGIN_FAILEDevents. The implicit grant flow is no longer supported:/api/oauth2/authnow accepts onlyresponse_type=code(soresponse_type=tokenis rejected), and the token endpoint accepts only theauthorization_code,password,client_credentialsandrefresh_tokengrant types. [cb9831058]
Improved
Saving objects in large instances: A save no longer leaves a record "processing" for minutes before it becomes searchable. Previously every term the object references was re-counted on every save; on large databases (millions of object↔term links) recomputing those counts dominated indexing, especially for common terms. A save now re-indexes only the terms whose link to the object actually changed — terms whose link is unchanged keep their count and are skipped — and each term's object count is read from an index-only scan instead of fetching every matching row. Deletes and undeletes still re-index the affected object's terms in full, so trashed objects keep dropping out of
/api/suggest. The upgrade rebuilds an index on theobject_termtable, which briefly locks it during the (already re-indexing) update. [a49ab9728]/api/tags:
POST /tagsnow follows a two-step protocol when tags omitted from the request payload would be deleted. If a deleted tag is still referenced in a place that can be cleaned up automatically (collection.create_object,objecttype_tag,pool_tag), the call returns202with atasks[]envelope that describes what would be removed and carries adelete_policy=remove_tagsconfirmation button; resend the identical request with that query parameter to confirm. If a deleted tag is referenced in a place that cannot be cleaned up automatically — object tags, the ACL of a right preset / pool / tag / objecttype, an objecttype column- or mask-filter, a workflow transition tag filter, or a path in the baseconfig — the call returns400withcode: TagsInUseand aparameters.usages[]array listing eachtag_id,contextand the affectedids(orrefsfor baseconfig paths) so the caller can resolve each reference and retry. [49a8222e9]/api/export (CSV / XLSX / XML): File-field columns now include the
iiif_urlanddeep_link_urlof each exported version alongside the existingurl. CSV/XLSX produce<field>[N].iiif_urland<field>[N].deep_link_url; XML adds<iiif_url>and<deep_link_url>tags inside each<version>.iiif_urlis populated for image versions whose recipe is IIIF-eligible (png/jpg/jp2/jpeg/webpup to 32000×32000 pixels),deep_link_urlwhenever the object UUID is known. Empty values are skipped, so columns appear only when there is a URL to emit. The same fields have always been available in JSON exports — this brings the sheet/XML formats in line. [dff5e821d]/api/export[merge]: Stop wiping unmapped tags during exiftool merge exports. Previously a mapping field with
xml_exportpaths but noeasydbsource emitted an empty value to exiftool, which clears that tag in the file — so a merge mapping that only configured a subset of fields ended up removing every other tag (e.g.CopyrightNoticewas lost). The new behavior is opt-in via anexiftool_export_omit_emptyflag on the mapping (and on the profile), set totrueinexport_merge.ymlandempty_export_merge.yml. Existing mappings keep their previous behavior unless theirprofilematches one of the merge profiles, in which case the migration enables the flag for them. Fields that have an expliciteasydbsource still emit empty values, so an intentional clear is still possible. [97e110670]/api/export & transport (ZIP): ZIP archives delivered by an export download or written by a transport (including the (s)FTP transport) are now Deflate-compressed instead of stored uncompressed, so the resulting
.zipis smaller. The packaged files themselves are unchanged. [7b57c3280]/eas, produce config: InDesign (INDD) files are now produced as multi-page documents instead of single raw images — reclassified from the
imageto theofficeclass sopdf2pagesrenders one image per page from the embedded XMP previews. An upgrade migration movesinddaccordingly in non-default produce configs (see Important). A recipe/extension mismatch no longer fails the whole produce config compile at startup; the offending extension is dropped with a warning. Existing INDD files keep the single image they were produced with before the update; to give them the page previews, re-produce them from/inspect/files: filter by theinddextension and run the Produce versions (produce_versions) action, which discards the old versions and re-runs each original through the new office-class pipeline. An INDD's pages are its embedded XMP previews, taken from whichever tag carries them — the multi-pagePageImageset, or a singleThumbnailImagewritten by older InDesign versions. A file with any embedded preview produces the page/preview versions (the count is reported intechnical_metadata.pages); only an INDD with no embedded preview at all produces no page/preview versions, instead of a single blank image. [56cfeb641] [2ee968d10] [55f936b68]/inspect/migration: Backup and restore now reconcile deleted objects and the links pointing at them. By default the restore drops link wrappers whose target is soft-deleted, or was purged but still survives only in a historic version — in either case the link can never resolve, so a backup-then-restore no longer leaves the linking object with a "(Purged / Deferred object)" ghost in every version. Two opt-in flags preserve the round-trip:
fylr backup --include-deletedincludes soft-deleted objects in the payload (exposed as "Include soft-deleted objects" on the Backup form), andfylr restore --include-deleted-linkedkeeps the link wrappers instead of stripping them (exposed as "Include links to deleted or purged objects" on the Restore form, covering both soft-deleted and purged targets). Used together, the deleted target is restored as such and its incoming links resolve to it; used alone on the restore, the links surface as_purged_or_deferredon read. See --include-deleted and --include-deleted-linked. [894e9564e] [4266cfd8f]/inspect/migration: Pools and objecttypes now carry their tag bindings — both the global tag list and any private tags scoped to that pool / objecttype — through the backup payload, so a backup-restore round-trip preserves the per-pool / per-objecttype private tags it previously dropped. [ae814db5f]
/inspect/migration: Restore now accepts a
rename-versionsparameter that renames file versions (renditions) as objects are uploaded into the target instance — useful when the source uses different version names than the target (e.g.video.1920p→1080p). An empty target removes the version. The Restore form exposes aFile class/Source version/Target versiontable that grows a row as the last one is filled, pre-populated from the previously stored restore parameters when a backup is selected. See renaming renditions during migration for the value grammar. [519b18a38]Rights / saving ACLs: A user who holds only
BAG_ACL(notBAG_WRITE) on a collection or pool can now change its_acl/_private_aclwithout also holdingBAG_WRITE.BAG_WRITEis still required when the request body changes the object itself (e.g. its displayname) or_owner, and an empty body still requiresBAG_WRITE. [7ca6bb518]Rights / permission errors: When a save or file exchange is refused because the user is missing a right's sub-permission rather than the right itself, the error now names that sub-permission in bracket notation instead of blaming the whole right. A user who may upload files but lacks the "update and remove allowed" option of "Upload File" is now told they are missing
asset_upload[allow_update_and_remove]("Upload File[Update and remove allowed]") rather thanasset_upload("Upload File"). The bracket notation matches the form already used for system rights. [b303d565c]Base config: Dependent fields in the base config editor are now hidden while the flag that enables them is off —
register.form, thedeep_link_accessandoai_pmhfields below theirenabledswitch,webdav.hotfolder_wait_sec, thejanitorfields belowactive, andloca.google_csv. This declutters the form viashow_script. [e4132041e]Plugins: Plugin callbacks now receive every system config parameter marked
unauthenticated_visible(e.g.appearance,name), not justlanguagesas before. A new parameter-levelunauthenticated_visibleflag lets you keep individual parameters out of the config handed to plugins. [c5460e665]Cookies: The
Secureflag on cookies set by fylr is now derived automatically fromfylr.externalURLinstead of being forced on for every cookie — anhttps://external URL getsSecurecookies, anhttp://one does not. This drops the 6.32fylr.debug.cookieAllowInsecureescape hatch (now removed; configs that still set it are ignored) and lets/inspect/login work on HTTP-only installs without extra configuration, which 6.32 had broken. Behind a TLS-terminating reverse proxy the cookies staySecureas long asexternalURLis thehttps://URL the browser uses. [5458bf5e5]/inspect/migration: Restore now accepts a
rename-versionsparameter that renames file versions (renditions) as objects are uploaded into the target instance — useful when the source uses different version names than the target (e.g.video.1920p→1080p). An empty target removes the version. The Restore form exposes aFile class/Source version/Target versiontable that grows a row as the last one is filled, and is pre-populated from the previously stored restore parameters when a backup is selected. See renaming renditions during migration for the value grammar. [78620]API documentation: a comprehensive audit and correction of the OpenAPI documentation (
/inspect/apidocs/) against the server code. Every endpoint now opens with a description and a brief per-method introduction, documents all URL parameters, the full request body and complete response coverage (the success case and every error code), and spells out each enum value. The OAuth2 / OpenID Connect endpoints (/api/oauth2/*) and the discovery document (/.well-known/openid-configuration) are now documented, and endpoints carry short "Differs from easydb 5" notes where fylr behaves differently. The same reference is now also published on GitBook at docs.fylr.io, and/inspect/apidocs/offers a GitBook-flavoured OpenAPI 3.0 spec download (datamodel stripped) next to the full OpenAPI 3.1 JSON. [66605]LDAP / SAML user mapping: The SSO login user-mapping can now target the user's address fields —
country,state,postal_code,town,street,house_numberandaddress_supplement— in addition to the existingreference,login,displayname,email,company,department,first_name,last_nameandphone. Map an IdP attribute to one of these keys in the LDAP or SAML User mapping table and the value is written to the matching field on the user at login; previously these keys were silently dropped. [8c1f31fa3]
Fixed
/api/search: a
type: "geo_shape"query that omits itsgeo_shapeobject orfieldreported an error naming a non-existentgeo_polygonkey; the message now names the realgeo_shapekey. [66605]bgtask metadata mapping: Two bugs that surfaced together via the ai-metadata plugin. (1) A new object version produced by an
overwrite_valuesrun was attributed to the previous version's author, so a task run by user B showed up in the change history as a change by user A — the version is now attributed to the user of the saving session. (2) When a mapping field targeted a custom-data-type sub-field (e.g.weblink.text_plain) and the recipe returned an empty string, overwrite mode replaced the whole CDT and silently cleared its other sub-fields (e.g.weblink.url); empty recipe results are now skipped. [b4480b92d]/api/search: Stop
date_rangeaggregations from reporting a phantom hit on the day after adate/datetime/daterangevalue. The indexer used to write an extra marker at the exclusive end of a value's range (the23:59:59Zsecond), which slipped into the next calendar day when an aggregation bucket carried a non-UTC offset — a1977-05-29value would then match a1977-05-30day bucket queried in+01:00. The forced re-index (see Important) clears the stray markers from existing objects. [609ada17e]/api/search: Map clustering (
geohash_grid) now reports a stablegeo_center. It used to be the centre of the geohash cell, which changes at every zoom level, so a fixed cluster of objects appeared to jump or duplicate as the user zoomed in on the map.geo_centeris now the actual centroid of the objects in the bucket and stays put across precision levels. [2004bbc32]OAuth login: Reworked handling of the redirect destination carried in the OAuth
stateparameter at the webapp callback. Same-origin destinations — a local path, or one matchingfylr.externalURL— are accepted by default; cross-origin destinations must now be allow-listed via the newfylr.services.webapp.loginAllowRedirectssetting, which matches host names with RFC 6125 wildcard rules (a single*is allowed only as the entire leftmost host label) and accepts a port wildcard —:*in place of the port matches any port (including none) on the same host, sohttp://localhost:*allows a frontend dev server regardless of which port it picked. The default config bakeshttps://*.web.fylr.dev,http://localhost:*andhttps://localhost:*into the allow-list; customer configs replace the list unless they useloginAllowRedirects+:to extend it orloginAllowRedirects-:to drop a baked-in entry. See also Important. [545536f31] [c395ff438] [7d8a69429]/api/eas/rput: Validate the URL passed to
rputagainst a configurable host blocklist before opening the outbound connection. The newfylr.eas.rput.blockedHostssetting accepts IP/CIDR, exact-hostname and single-label-wildcard entries (each optionally pinned to a port). The compiled-in default blocks loopback, link-local and private (RFC1918 / ULA) ranges (127.0.0.0/8,::1/128,169.254.0.0/16,fe80::/10,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,fc00::/7). fylr's own internal services are added automatically on their exact host:port. Host names from the URL are resolved and the connection is pinned to the resolved address. The API listener stays reachable so the existing tile-restore workflow (rputon a/api/v1/eas/zoom/...URL) keeps working. [e7fdafbab] [69552956b]/api/eas:
iiif_urlandzoom_url(signed URLs, and those carrying anobj_uuid) were broken when a version name contained a/; the version name is now escaped properly. [327e22cc2]Datamodel / expert search: The auto-generated all-fields ("expert search") mask no longer defaults
search.facet=trueon every column — only on the column types the webfrontend renders a facet toggle for (boolean, date, datetime, daterange, link). This stops the facet flag from riding along silently on text/file columns. Only newly created masks pick up the corrected default; existing masks keep their storedfacetflags. [a179d2337] [ed735999d]/api/v1/user and /api/v1/group: Responses include the
_aclfield only for callers that holdsystem.user/system.root(for/user) orsystem.group/system.root(for/group). Applies to GET, list, POST and DELETE on both endpoints./api/searchresults fortype=userandtype=groupno longer include_acl; fetch the object via the endpoint above as an administrator to read its ACL. [68a06c30b]Plugin loader: Plugin paths are now treated as literal directories; the long-broken glob support was dropped. A missing path is logged as an error and skipped, so misconfigurations stay visible. [37cc4628b] [fecad83b1]
Base config: Fixed loading of the client block time from the base config. [451fcc939]
/api/db: Fixed an occasional deadlock between the indexer and a concurrent purge that could fail
DELETE /db/<table>?delete_policy=purgewith a serialization error under parallel load. [86a536369]Logout: Fixed a nil-pointer crash during logout. [a1781941b]
Pool / objecttype captions & watermarks: Changing a pool's or objecttype's caption or watermark configuration and confirming the resync could leave some file renditions rendered with the previous configuration. The cache id that tells file-produce workers to reload base data was bumped just after the change had committed instead of together with it, so a worker could start the queued resync, read the new configuration, and still re-render against the stale cache. The bump now commits atomically with the change, so every reader observes the new configuration. This affects all cached base data — pools, objecttypes, masks, datamodel, collections, transitions, tags, ACL groups and plugins — not only captions. [02c1239c8]
Indexer: Rejected index jobs for base types (collections, pools, groups, users, messages, terms) are now re-queued and retried, the same as object jobs. Previously, when the search cluster rejected jobs under load (
rejected_execution_exception), only objects were re-queued; a base type rejected this way stayed unindexed — e.g. a newly created group or pool remainedfound:false. The base-type index-error event also no longer records an empty type. [f6386a9cd]Indexer: Long localized free text on a base type (a message body, a collection or pool description, a group display name) no longer breaks indexing. The value was indexed as a single keyword term, and once it passed Lucene's 32766-byte limit the search cluster rejected the whole document ("immense term") — the object dropped out of the index and vanished from the frontend, and a re-index could not recover it. The text is now chunked like object text fields already are; this release's re-index repairs existing affected objects. [5216dcc85]
Docker image (TIFF clipping paths): The bundled ImageMagick is pinned to the last good upstream patchlevel,
7.1.2-21(from a Debian snapshot). ImageMagick7.1.2-23broke rendering of embedded TIFF clipping paths — the clip step that cuts the background produced a blank, fully transparent preview, so every clipped rendition (small, preview, huge, zoom, full) came out empty. The pin is a temporary workaround and will be removed once a fixed ImageMagick reaches Debian. [b74edd8ef]
Frontend
New
Metadata Mapping – omit empty fields on Exiftool export : Added a new "Omit empty fields from Exiftool export" checkbox in the general tab of the mapping editor. It only appears for fylr mappings whose profile has Exiftool export enabled, and lets users opt in to skipping fields without an easydb source instead of clearing the tag in the file. (467a7ad1c)
Search by multiple object IDs : Search now supports filtering by several system object IDs from a single URL parameter (
?sids=1,2,3), generating one combined query element instead of one per ID. This makes shared search URLs shorter and easier to build when targeting many objects at once. (d718b8b24)Nested Table Popover events : Added two new events fired when a nested popover is opened and closed, giving plugins and other logic a hook to be notified of these events. (cb0891100)
Base Config – show_script in table fields : Added support for
show_scriptin table field types. Fields in table rows can now be hidden based on the evaluation of ashow_scriptexpression. (a01dda7e3)
Improved
Task Manager – improved task editor : Improved the task editor and removed the beta limitations. (42d3f19ff)
Task Manager – layout tweaks : Swapped the Module/Title order and reverted sections to headlines. (9db7730fe)
Editor – incompatible tags on pool change : When changing the pool, incompatible tags are now removed and the user is warned before saving. (0272cddee)
Secure token handling on uploads : The authentication token is no longer sent as a URL parameter in PUT/POST requests for EAS uploads; it is now passed in the request headers. (8d9aa47c6)
Browser context menu on text and inputs : The context-menu override on right click is now disabled when the target is selected text or inside an input, so the native browser menu (copy/paste, etc.) works as expected when handling text. (787728a6b)
Search – "remove all" button in ez5 : Enabled the "remove all" button in the search for ez5. (96719c1c4)
CUI.xhr – custom request headers : Added support in
CUI.xhrfor adding custom headers to a request. (CUI, 0d889151)Tag Manager – grouped "tags in use" errors : The
TagsInUseerror usages are now rendered grouped by tag with clickable links, making it easier to find where a tag is still in use. (3022aa517)Customize templates – localizable preview column : The preview column in customize templates is now localizable. (8e01b4e6f)
Customize templates – localizable tab titles : The tab titles in customize templates are now localizable. (b4238189d)
Fixed
Permissions – share dialog with only BAG_ACL : Users with only
BAG_ACL(and noBAG_WRITE) can now open the share dialog of a collection or pool and save their permission changes; only the ACL fields are sent so the backend accepts the save instead of rejecting it. (6b8911497)Logout in cross-server mode : Fixed logout in cross-server mode so the request is sent to the destination backend instead of the frontend server, and the user is redirected back to the frontend once the backend completes the logout. (85f62dae4)
Export inspect icon : Fixed a bug that hid the inspect icon for exports when not in the main search view. (a699881e1)
Connector availability check : Fixed an error when checking connector availability for the new version of the connector plugin. (964edeb81)
Print Manager : Fixed harmless warnings from print assertions, stopped the frontend from trying to render tooltips in print scenarios on some browsers like Firefox, and turned a
cUI.dom.emptyerror into a log warning instead of throwing. (1463feb7a)Cross-instance request headers : Fixed an unsafe header in cross-instance requests (such as the connector) and cleared some harmless console warnings in connector scenarios. (3dbff6667)
User preferences for LDAP/SSO users : Fixed the visibility of the user webfrontend preferences tab in the user manager so it is shown for LDAP and SSO users. (84c34883b)
Hierarchy "not found" label : Fixed the "not found" label in search for hierarchy mode set to auto, which was wrongly using the top-level "not found" variant. (5cae2e42c)
CSV importer race condition : Fixed a race condition when building the CSV importer configurator panel, which could render before the proper dbinfo data was available and throw an error. (47b32f9bd)
Filter pool label for remote pools : Fixed the filter pool label for remote pools. (ff89256d9)
Console error when no user is selected : Fixed a console error that occurred when no user was selected. (de6f0dc94)
Ctrl+S in editor : Fixed the Ctrl+S shortcut in the editor. (5058948ce)
NoMasksForCreate API error : Fixed the
NoMasksForCreateAPI error that occurred on a rare edge case after login. (e5f9d669f)CUI.DOM.empty – less destructive assertion : Made the
CUI.DOM.emptyassertion less destructive: it now logs a warning instead of throwing an error that could break frontend logic. (CUI, ade1eedb)Parent Column link in "Short" rendering : Fixed the link to the parent object in the parent field when the object is rendered as "Short"; the generated search was incorrect. (ecb892abe)
Base Config – guard for fields without a name : Added a guard so Base Config no longer dies when the server sends a field without a name in the base config file worker definition (which can happen, for example, when a buggy plugin tries to add configuration). (80314380a)
Datamodel – clean up stray facet flag : The Datamodel manager now detects and cleans up an old internal
search.facetsetting that some masks were still carrying on fields where it shouldn't be. When opening the manager, the user is prompted to re-save the masks so the leftover flag is removed and hidden fields stop showing up in expert search. (344f68c2c)Task Manager – output-only details form : The form that contains the task details is now rendered as "output-only", applying a slightly lesser margin. (c9f329773)
Fields – navigation toolbar visibility : Made sure the navigation toolbar is actually visible so its margin is applied. (c87f782a6)
Last updated