From 3fd45ad05fe59dab6b2892600a936c68d088ee7e Mon Sep 17 00:00:00 2001 From: Kaushal Shriwas Date: Thu, 26 Feb 2026 17:53:57 +0530 Subject: [PATCH 1/3] fix: enforce link_filters on link fields server-side --- frappe/client.py | 2 +- frappe/public/js/frappe/form/controls/link.js | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/frappe/client.py b/frappe/client.py index 0019e844eb..60a8983d4e 100644 --- a/frappe/client.py +++ b/frappe/client.py @@ -465,7 +465,7 @@ def validate_link_and_fetch( ) if not search_result: - return {} # does not exist or filtered out + return {} values = None is_virtual_dt = bool(meta.get("is_virtual")) diff --git a/frappe/public/js/frappe/form/controls/link.js b/frappe/public/js/frappe/form/controls/link.js index 74d62c6382..cbd41491cb 100644 --- a/frappe/public/js/frappe/form/controls/link.js +++ b/frappe/public/js/frappe/form/controls/link.js @@ -870,6 +870,7 @@ frappe.ui.form.ControlLink = class ControlLink extends frappe.ui.form.ControlDat validate_link_and_fetch(value) { const args = this.get_search_args(value); if (!args) return; + const has_filters = !!(args.filters && Object.keys(args.filters).length); const columns_to_fetch = Object.values(this.fetch_map); @@ -938,6 +939,16 @@ frappe.ui.form.ControlLink = class ControlLink extends frappe.ui.form.ControlDat .then((response) => { if (!response) return; + if (!response.name && has_filters) { + frappe.show_alert({ + message: __("{0}: {1} did not match any results.", [ + __(this.df.label || this.df.fieldname), + value, + ]), + indicator: "red", + }); + } + update_dependant_fields(response); return response.name; }); From dccf136dd4446d91d3bd0dba1411609ef26898fb Mon Sep 17 00:00:00 2001 From: Kaushal Shriwas Date: Wed, 11 Mar 2026 15:56:41 +0530 Subject: [PATCH 2/3] chore: use appropriate comment for clarity --- frappe/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/client.py b/frappe/client.py index 60a8983d4e..b43e2afac3 100644 --- a/frappe/client.py +++ b/frappe/client.py @@ -465,7 +465,7 @@ def validate_link_and_fetch( ) if not search_result: - return {} + return {} # Either the record does not exist or was excluded by link_filters values = None is_virtual_dt = bool(meta.get("is_virtual")) From b31067e769ce5fa6a87e9966ae1dd99757ea15e4 Mon Sep 17 00:00:00 2001 From: Kaushal Shriwas Date: Thu, 12 Mar 2026 13:07:53 +0530 Subject: [PATCH 3/3] refactor: move has_filters declaration to usage location --- frappe/public/js/frappe/form/controls/link.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/form/controls/link.js b/frappe/public/js/frappe/form/controls/link.js index cbd41491cb..c81e5c2c6d 100644 --- a/frappe/public/js/frappe/form/controls/link.js +++ b/frappe/public/js/frappe/form/controls/link.js @@ -870,7 +870,6 @@ frappe.ui.form.ControlLink = class ControlLink extends frappe.ui.form.ControlDat validate_link_and_fetch(value) { const args = this.get_search_args(value); if (!args) return; - const has_filters = !!(args.filters && Object.keys(args.filters).length); const columns_to_fetch = Object.values(this.fetch_map); @@ -939,6 +938,7 @@ frappe.ui.form.ControlLink = class ControlLink extends frappe.ui.form.ControlDat .then((response) => { if (!response) return; + const has_filters = !!(args.filters && Object.keys(args.filters).length); if (!response.name && has_filters) { frappe.show_alert({ message: __("{0}: {1} did not match any results.", [