ORA-04040: Stored Procedure, Function, Package, or Package Body Not Found
ORA-04040 is thrown by Oracle Database when it cannot locate a stored procedure, function, package, or package body referenced in your code. This typically happens when the object doesn't exist, has been dropped, has a name mismatch, or the current user lacks the necessary privileges to access it. It is one of the most common errors encountered after application deployments or schema migrations.
Top 3 Causes
1. The Object Does Not Exist in the Database
The object was never created, was accidentally dropped, or the deployment script was incomplete.
-- Check if the object exists
SELECT OWNER, OBJECT_NAME, OBJECT_TYPE, STATUS
FROM DBA_OBJECTS
WHERE OBJECT_NAME = 'CALCULATE_SALARY'
AND OBJECT_TYPE IN ('PROCEDURE','FUNCTION','PACKAGE','PACKAGE BODY');
-- If missing, recreate it
CREATE OR REPLACE PROCEDURE CALCULATE_SALARY (
p_emp_id IN NUMBER,
p_salary OUT NUMBER
)
AS
BEGIN
SELECT SALARY
INTO p_salary
FROM EMPLOYEES
WHERE EMPLOYEE_ID = p_emp_id;
EXCEPTION
WHEN NO_DATA_FOUND THEN
p_salary := 0;
END CALCULATE_SALARY;
/
2. Object Name Typo or Wrong Schema Reference
Calling the object with a misspelled name or omitting the correct schema prefix is a very common mistake.
-- Find the correct owner and name
SELECT OWNER, OBJECT_NAME, OBJECT_TYPE
FROM DBA_OBJECTS
WHERE UPPER(OBJECT_NAME) LIKE '%CALCULATE%'
AND OBJECT_TYPE IN ('PROCEDURE','FUNCTION','PACKAGE','PACKAGE BODY');
-- Always qualify with the correct schema
BEGIN
HR.CALCULATE_SALARY(p_emp_id => 100, p_salary => :v_out);
END;
/
3. Missing EXECUTE Privilege or Synonym
When a user tries to call an object in another schema without the proper EXECUTE grant or a synonym pointing to it, Oracle returns ORA-04040 rather than a privilege error — intentionally obscuring object existence for security.
-- Grant EXECUTE privilege
GRANT EXECUTE ON HR.CALCULATE_SALARY TO APP_USER;
-- Create a public synonym so any user can call it without schema prefix
CREATE PUBLIC SYNONYM CALCULATE_SALARY
FOR HR.CALCULATE_SALARY;
-- Verify privileges
SELECT PRIVILEGE, TABLE_NAME, GRANTOR
FROM DBA_TAB_PRIVS
WHERE TABLE_NAME = 'CALCULATE_SALARY'
AND GRANTEE = 'APP_USER';
Quick Fix Solutions
Recompile INVALID objects — The object may exist but be in an INVALID state due to dependency changes.
-- Recompile a single object
ALTER PROCEDURE CALCULATE_SALARY COMPILE;
ALTER PACKAGE HR_PKG COMPILE BODY;
-- Recompile all invalid objects in a schema
EXEC DBMS_UTILITY.COMPILE_SCHEMA(SCHEMA => 'HR', COMPILE_ALL => FALSE);
-- Detect broken synonyms
SELECT SYNONYM_NAME, TABLE_OWNER, TABLE_NAME
FROM DBA_SYNONYMS S
WHERE NOT EXISTS (
SELECT 1 FROM DBA_OBJECTS O
WHERE O.OWNER = S.TABLE_OWNER
AND O.OBJECT_NAME = S.TABLE_NAME
);
Prevention Tips
- Automate post-deployment validation: Add a script to your CI/CD pipeline that counts INVALID objects after every release. Fail the pipeline if the count is greater than zero.
-- Post-deployment health check
SELECT COUNT(*) AS INVALID_COUNT
FROM DBA_OBJECTS
WHERE STATUS = 'INVALID'
AND OWNER = 'HR';
-
Standardize privilege and synonym management: Always include
GRANT EXECUTEandCREATE SYNONYMsteps as mandatory items in your deployment checklist. Periodically auditDBA_TAB_PRIVSandDBA_SYNONYMSto catch permission drift before it causes production incidents.
Related Errors
- ORA-04043 — Object does not exist (similar error for tables and views)
- ORA-06550 — PL/SQL compilation error often seen alongside ORA-04040
- ORA-00942 — Table or view does not exist, often the root cause of INVALID procedures
- ORA-04068 — Package state discarded after recompilation
📖 Want a more detailed guide?
Check out the full in-depth version (Korean) on oraerror.com — includes detailed analysis, additional SQL examples, and prevention tips.
Top comments (0)