Skip to content
Microsoft SQL Server

SQL Server Error 2812

Could not find stored procedure

Applies to: All supported SQL Server versions (2016 to 2025), Azure SQL Database, Azure SQL Managed Instance
Last technically reviewed 23 October 2026 on SQL Server 2025 (17.0.1145.4)
The full message
Msg 2812, Level 16, State 62, Line 1
Could not find stored procedure 'dbo.usp_GetCustomer'.
Other forms of this message
A three-part name, when the procedure is not in the named database (reproduced)
Msg 2812, Level 16, State 62, Line 1
Could not find stored procedure 'master.dbo.usp_Nope'.
The procedure exists but the caller lacks EXECUTE permission: error 229, not 2812 (reproduced)
Msg 229, Level 14, State 5, Procedure dbo.usp_GetCustomer, Line 1
The EXECUTE permission was denied on the object 'usp_GetCustomer', database 'AppDb', schema 'dbo'.
Error number
2812
Severity
16 (user-correctable error)
State
62
Product
Microsoft SQL Server Database Engine
Versions
All supported SQL Server versions (2016 to 2025), Azure SQL Database, Azure SQL Managed Instance
Last reviewed
23 October 2026

What it means

Error 2812 means EXEC named a stored procedure that SQL Server cannot find under that name, in that schema, in the current (or named) database.

When a batch runs EXEC name, SQL Server resolves the name at execution time: in the database named in the call or, if none, the current database; in the schema named in the call or, if none, the caller's default schema and then dbo. If nothing matches, the statement fails with 2812 at severity 16. The text in quotes is exactly the name the engine tried to resolve, which is often the quickest clue: a typo, a missing schema, or something that is not a procedure name at all.

That last case is common with dynamic SQL: EXEC @sql without parentheses treats the contents of @sql as a procedure name, so the message quotes your whole SELECT statement. EXEC (@sql) or sp_executesql runs it as a batch instead. If the procedure exists but you are not allowed to run it, SQL Server raises error 229 rather than 2812.

Common causes

  • A typo in the procedure name, or a procedure that was renamed or never deployed to this environment.
  • The connection is in a different database from the one that holds the procedure (for example master after login).
  • The procedure is in a schema other than dbo or the caller's default schema, and the call omits the schema.
  • EXEC @sql without parentheses, which treats the dynamic SQL string as a procedure name.
  • A procedure name copied from another product or version (for example an undocumented system procedure that does not exist here).

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.

Check which database and schema the call resolves in

SELECT DB_NAME() AS current_database, SCHEMA_NAME() AS default_schema;
What to look for

If current_database is not the database that holds the procedure, the call needs a USE statement, a three-part name, or a corrected connection string.

Search for procedures with a similar name in any schema

SELECT SCHEMA_NAME(p.schema_id) AS schema_name, p.name, p.create_date, p.modify_date
FROM sys.procedures AS p
WHERE p.name LIKE N'%GetCustomer%'
ORDER BY p.name;
What to look for

The real spelling and schema of the procedure, such as Billing.usp_GetCustomer. No rows means it is not in this database, or you cannot see it.

Look for the procedure in every database on the instance

OBJECT_ID with a three-part name checks each database without switching to it. Replace the name with the one from the message.

SELECT d.name AS database_name
FROM sys.databases AS d
WHERE OBJECT_ID(QUOTENAME(d.name) + N'.dbo.usp_GetCustomer', N'P') IS NOT NULL;
What to look for

The databases that contain dbo.usp_GetCustomer. Databases you cannot access are skipped.

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 procedure with its schema and exact name

Client or network side

Correct the spelling and add the schema in the calling code, for example EXEC Billing.usp_GetInvoice @id = 1; instead of EXEC usp_GetInvoice @id = 1;. Schema-qualified calls avoid 2812 when the caller's default schema differs.

Connect to, or name, the right database

Client or network side

Set Initial Catalog (Database) in the connection string, or use a three-part name such as EXEC Shop.dbo.usp_GetCustomer @id = 1; when calling across databases.

Run dynamic SQL as a batch, not as a procedure name

Client or network side

In the script or procedure that builds the statement, write EXEC (@sql); with parentheses, or better EXEC sp_executesql @sql; with a parameter list for any values. Without parentheses EXEC treats the string as the name of a procedure. Running the statement does whatever the dynamic SQL does, so review it first.

Deploy the missing procedure

Changes schema

If the procedure exists in development but not here, deploy it from source control. CREATE OR ALTER is safe to re-run.

CREATE OR ALTER PROCEDURE dbo.usp_GetCustomer
    @id INT
AS
SELECT id, name FROM dbo.Customers WHERE id = @id;

Examples

A typo in the procedure name

CREATE TABLE dbo.Customers (id INT PRIMARY KEY);
GO
CREATE PROCEDURE dbo.usp_GetCustomer @id INT AS SELECT id FROM dbo.Customers WHERE id = @id;
GO
EXEC dbo.usp_GetCustomr @id = 1;  -- Customer is misspelled
Result
Msg 2812, Level 16, State 62, Line 1
Could not find stored procedure 'dbo.usp_GetCustomr'.

Reproduced on SQL Server 2025 (17.0.1145.4), 23 October 2026.

A procedure in another schema called without the schema

CREATE SCHEMA Billing;
GO
CREATE PROCEDURE Billing.usp_GetInvoice @id INT AS SELECT @id AS id;
GO
EXEC usp_GetInvoice @id = 1;  -- resolves in dbo, not Billing
Result
Msg 2812, Level 16, State 62, Line 1
Could not find stored procedure 'usp_GetInvoice'.

Reproduced on SQL Server 2025 (17.0.1145.4), 23 October 2026.

EXEC @sql without parentheses

DECLARE @sql NVARCHAR(MAX) = N'SELECT name FROM sys.objects';
EXEC @sql;  -- treated as a procedure name
Result
Msg 2812, Level 16, State 62, Line 2
Could not find stored procedure 'SELECT name FROM sys.objects'.

Reproduced on SQL Server 2025 (17.0.1145.4), 23 October 2026.

How to prevent it

Schema-qualify every procedure call (EXEC dbo.usp_Name), set the database in the connection string rather than relying on the login's default database, and deploy procedures from source control so every environment has the same set.

For dynamic SQL, use sp_executesql with parameters as the standard pattern, so a string is never mistaken for a procedure name. The stored procedures and functions lesson covers creating and calling procedures.

Common questions

The procedure exists in SSMS. Why does my application get 2812?

The application is probably connected to a different database (often master, the default) or uses a login whose default schema is not the procedure's schema. Check Initial Catalog in the connection string and qualify the call with the schema.

Why does the message show my whole SELECT statement as the procedure name?

You ran EXEC @sql without parentheses. SQL Server treated the string as a procedure name. Use EXEC (@sql) or sp_executesql.

Do I get 2812 if I lack permission on the procedure?

In our test, no: a user without EXECUTE permission received error 229 (permission denied), not 2812. 2812 means the name itself could not be resolved.

Learn more on CodeWithSQL

Official documentation

Last technically reviewed 23 October 2026; examples and diagnostics run on SQL Server 2025 (17.0.1145.4). Message text checked against the engine's sys.messages catalogue.

Still stuck on a SQL Server error?

Browse the full SQL Server error library, or get hands-on help from an experienced SQL professional.