- Error number
- 4121
- Severity
- 16 (user-correctable error)
- State
- 1
- Product
- Microsoft SQL Server Database Engine
- Versions
- All supported SQL Server versions (2016 to 2025), Azure SQL Database, Azure SQL Managed Instance
- Category
- Syntax & Object Resolution
- Last reviewed
- 24 October 2026
On this page
What it means
Error 4121 means a call written as prefix.name(...) could not be matched to a user-defined function in that schema, nor to a method on a column called prefix, so SQL Server cannot tell what you are calling.
In T-SQL the syntax x.Name(...) is ambiguous: it can be a scalar user-defined function Name in schema x, a user-defined aggregate, or a method called on a column x (as with xml, geography or hierarchyid columns). SQL Server tries both readings. When neither works, it raises 4121 at severity 16 and quotes both interpretations: the first name is the prefix read as a column, the second is the whole call read as a function. Usually the prefix is meant to be a schema, and the function is not in it.
Scalar functions must always be called with a schema prefix. Without one, SQL Server only looks among built-in functions and raises error 195 instead. With a prefix, the schema must be the one the function lives in: SQL Server does not fall back to dbo or to your default schema. Inside a stored procedure the check is deferred, so the procedure is created successfully and fails with 4121 only when it runs, much like error 208 for missing tables.
Common causes
- The function lives in another schema (for example hr or util) than the one in the call, often dbo by habit.
- A typo in the function name, or a function that was never deployed to this database.
- A table alias used as the prefix of a function call, such as
s.FullName(...), instead of the schema. - An xml method such as
.value()or.query()called on a column that is nvarchar, not xml. - A user-defined aggregate (CLR) that is not registered in the current database.
Diagnose it
Read-only These queries only read metadata and dynamic management views. They do not change data, permissions or configuration, so they are safe to run first.
Find the function in any schema
SELECT SCHEMA_NAME(o.schema_id) AS schema_name, o.name, o.type_desc
FROM sys.objects AS o
WHERE o.name LIKE N'%FullName%'
AND o.type IN ('FN', 'IF', 'TF', 'FS', 'FT', 'AF'); The schema the function really belongs to. No rows means it does not exist in this database, or the name is spelled differently.
Check the type of a column you call a method on
SELECT c.name AS column_name, TYPE_NAME(c.user_type_id) AS data_type
FROM sys.columns AS c
WHERE c.object_id = OBJECT_ID(N'dbo.Documents')
ORDER BY c.column_id; Methods such as value(), query() and exist() exist only on xml. A column shown as nvarchar or varchar cannot take them.
Find procedures that reference a function name
Because of deferred name resolution, procedures with a wrong call are created without error. This search finds modules that mention the name so you can fix them all.
SELECT OBJECT_SCHEMA_NAME(m.object_id) AS schema_name, OBJECT_NAME(m.object_id) AS module_name
FROM sys.sql_modules AS m
WHERE m.definition LIKE N'%FullName(%'; Each module that calls the function. Check that every call uses the schema found by the first query.
How to fix it
Each fix is labelled with what it changes. Try read-only checks and the least invasive fix first, and test changes outside production.
Call the function with the schema it belongs to
Read-onlyUse the schema returned by the first diagnostic. Keep the table alias for columns and the schema for the function.
SELECT payroll.FullName(s.first_name, s.last_name) AS full_name
FROM dbo.Staff AS s;
Convert text to xml before calling xml methods
Read-onlyIf the column holds XML as text, convert it first. TRY_CONVERT returns NULL for rows that are not well-formed XML instead of failing the query.
SELECT d.id,
TRY_CONVERT(xml, d.body).value('(/invoice/@total)[1]', 'decimal(10,2)') AS total
FROM dbo.Documents AS d;
Deploy the function where the callers expect it
Changes schemaIf many callers use another schema and the function is missing there, create it (or move it with ALTER SCHEMA ... TRANSFER). Moving it breaks callers that use the old schema, so search modules first with the third diagnostic.
ALTER SCHEMA dbo TRANSFER payroll.FullName;
Examples
The function lives in another schema
CREATE SCHEMA payroll;
GO
CREATE FUNCTION payroll.FullName (@first nvarchar(50), @last nvarchar(50))
RETURNS nvarchar(101) AS BEGIN RETURN @first + N' ' + @last; END;
GO
CREATE TABLE dbo.Staff (id INT PRIMARY KEY, first_name NVARCHAR(50), last_name NVARCHAR(50));
SELECT dbo.FullName(first_name, last_name) AS full_name -- it is payroll.FullName
FROM dbo.Staff;
Msg 4121, Level 16, State 1, Line 3 Cannot find either column "dbo" or the user-defined function or aggregate "dbo.FullName", or the name is ambiguous.
Reproduced on SQL Server 2025 (17.0.1145.4), 23 October 2026.
A table alias used in place of the schema
CREATE FUNCTION dbo.FullName (@first nvarchar(50), @last nvarchar(50))
RETURNS nvarchar(101) AS BEGIN RETURN @first + N' ' + @last; END;
GO
CREATE TABLE dbo.Staff (id INT PRIMARY KEY, first_name NVARCHAR(50), last_name NVARCHAR(50));
SELECT s.FullName(s.first_name, s.last_name) AS full_name -- s is the table alias
FROM dbo.Staff AS s;
Msg 4121, Level 16, State 1, Line 3 Cannot find either column "s" or the user-defined function or aggregate "s.FullName", or the name is ambiguous.
Reproduced on SQL Server 2025 (17.0.1145.4), 23 October 2026.
An xml method called on an nvarchar column
CREATE TABLE dbo.Documents (id INT PRIMARY KEY, body NVARCHAR(MAX)); -- XML stored as text
SELECT body.value('(/invoice/@total)[1]', 'decimal(10,2)') AS total
FROM dbo.Documents;
Msg 4121, Level 16, State 1, Line 3 Cannot find either column "body" or the user-defined function or aggregate "body.value", or the name is ambiguous.
Reproduced on SQL Server 2025 (17.0.1145.4), 23 October 2026.
How to prevent it
Keep shared functions in one well-known schema and always call them with that two-part name. After a deployment, run a quick smoke test that executes each changed procedure, because deferred name resolution lets a wrong call through CREATE PROCEDURE unnoticed.
Store XML in xml columns if you plan to query inside it. For how scalar functions are created and called, see stored procedures and functions.
Common questions
Why must I write dbo. in front of my own function?
Scalar user-defined functions must be called with at least a two-part name. A one-part name is looked up only among built-in functions, which gives error 195.
My procedure was created without errors. Why does it fail with 4121 now?
SQL Server resolves function names when the procedure is compiled for execution, not when it is created. A missing or misnamed function is only reported on the first run.
What does "or the name is ambiguous" mean here?
The same text could be a column method call or a function call. The message lists both readings because SQL Server could not resolve either; it rarely means two functions match.
Learn more on CodeWithSQL
Official documentation
- CREATE FUNCTION (Transact-SQL)
- Execute user-defined functions
- value() method (xml data type)
- Database Engine events and errors 4000 to 4999
Last technically reviewed 24 October 2026; examples and diagnostics run on SQL Server 2025 (17.0.1145.4). Message text checked against the engine's sys.messages catalogue.