- Error code
- PLS-00201
- Product
- Oracle Database
- Versions
- Oracle Database 19c, 21c, 23ai and 26ai (same wording)
- Category
- PL/SQL & Triggers
- Last reviewed
- 24 October 2026
On this page
What it means
PLS-00201 means the PL/SQL compiler could not resolve a name: it is misspelt, not declared in scope, does not exist, or exists but the code is not allowed to see it, which Oracle deliberately reports the same way.
Every name in PL/SQL code (a variable, a table in a %TYPE, a procedure, a package) must resolve to something the compiler can see. If it cannot, it reports PLS-00201 with the name as written. In an anonymous block this appears under ORA-06550 with the line and column; for a stored unit it appears in SHOW ERRORS or USER_ERRORS, and the unit is left invalid.
Oracle's reference adds two points that explain most puzzling cases. First, if the item exists but you have no privilege on it, you are told only that it is not declared, for security reasons. Second, if the privilege was granted only through a role, this is expected: stored procedures, functions, packages, triggers and views run in the security domain of the owner with no roles enabled except PUBLIC. That is why a SELECT or call that works in your session can fail inside a procedure you create.
If the first part of a dotted name resolves but the part after the dot does not (a missing procedure inside an existing package, for example), the error is the related PLS-00302 "component must be declared" instead.
Common causes
- A misspelt variable, parameter or subprogram name, or one declared in an inner block and used outside it.
- The object exists in another schema and is referenced without the schema prefix, and there is no synonym for it.
- The owner of the stored unit has the privilege only through a role (for example EXECUTE on a package granted to a role), and roles are not enabled in definer's-rights stored code.
- There is no privilege at all on the object, or it was dropped or not yet created in this database or PDB.
- A quoted identifier is used with different case:
"Hello"and"HELLO"are different names.
Diagnose it
Read-only These queries only read the data dictionary (USER_, ALL_ and DBA_ views) and dynamic performance views (V$). They do not change data, privileges or settings, so they are safe to run first. DBA_ and V$ views need the matching privileges.
Does the object exist, and who owns it?
SELECT owner, object_name, object_type, status
FROM all_objects
WHERE object_name = 'ORDER_API'
ORDER BY owner; ALL_OBJECTS lists only objects you can access. No row means it does not exist or you have no privilege on it; a DBA can tell which by querying DBA_OBJECTS (DBA privileges needed).
Is the privilege granted directly or only through a role?
Run these as the owner of the stored unit (here REPORTING). Only a direct grant to that user, or to PUBLIC, counts inside definer's-rights stored code.
-- direct grants (and grants to PUBLIC)
SELECT grantor, grantee, table_schema, table_name, privilege
FROM all_tab_privs
WHERE table_schema = 'SHOP' AND table_name = 'ORDER_API';
-- grants that reach you only through a role
SELECT role, owner, table_name, privilege
FROM role_tab_privs
WHERE owner = 'SHOP' AND table_name = 'ORDER_API'; If the privilege appears only in ROLE_TAB_PRIVS, that explains the error: it works in your session but not in the procedure.
Is there a synonym for the name you used?
SELECT owner, synonym_name, table_owner, table_name
FROM all_synonyms
WHERE synonym_name = 'ORDER_API';
SELECT SYS_CONTEXT('USERENV', 'CURRENT_SCHEMA') AS current_schema,
SYS_CONTEXT('USERENV', 'SESSION_USER') AS session_user
FROM dual; Whether an unqualified name can resolve through a private or PUBLIC synonym, and which schema unqualified names are looked up in.
See every compile error of the unit
SELECT line, position, text
FROM all_errors
WHERE owner = 'REPORTING'
AND name = 'DAILY_ORDERS'
ORDER BY sequence; The PLS-00201 lines with their positions, and any errors that follow from them.
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.
Correct the name, its scope or its schema prefix
Changes schemaFix the spelling, declare the variable in a block that encloses the place it is used, or qualify the object with its owner. Recompile the unit afterwards.
CREATE OR REPLACE PROCEDURE reporting.daily_orders
IS
v_total NUMBER := 0;
BEGIN
shop.order_api.recalculate(v_total); -- schema-qualified
END;
/
Grant the privilege directly to the owner of the unit
Changes permissionsThe owner of the object (or a user allowed to grant it) grants exactly the privilege the code needs, directly to the schema that owns the procedure, then the procedure is recompiled. Oracle notes that roles granted to a PL/SQL unit do not affect compilation, so granting a role to the procedure does not fix PLS-00201.
Caution: Grant only the specific privilege on the specific object (EXECUTE on one package, SELECT on one table). Do not grant broad ANY privileges or DBA to make the error go away.
-- as SHOP (the owner of ORDER_API)
GRANT EXECUTE ON shop.order_api TO reporting;
-- as REPORTING
ALTER PROCEDURE reporting.daily_orders COMPILE;
Create a synonym if code should use an unqualified name
Changes schemaA private synonym lets REPORTING refer to ORDER_API without the prefix. It does not grant any privilege: the direct grant above is still needed.
CREATE SYNONYM reporting.order_api FOR shop.order_api;
Examples
A package that is granted only through a role
Not reproduced here: no Oracle Database is installed for this site. The message is from Oracle's error reference and the layout follows the SHOW ERRORS output documented in the SQL*Plus reference; names and positions are illustrative, and SHOW ERRORS also lists a "PL/SQL: Statement ignored" line for the same statement. The cause is the documented rule that roles are not enabled in stored definer's-rights code.
-- REPORTING can run SHOP.ORDER_API from its own session, through role APP_USER
CREATE OR REPLACE PROCEDURE daily_orders IS
BEGIN
shop.order_api.recalculate;
END;
/
SHOW ERRORS
Warning: Procedure created with compilation errors. Errors for PROCEDURE REPORTING.DAILY_ORDERS: LINE/COL ERROR -------- ----------------------------------------------------------- 3/3 PLS-00201: identifier 'SHOP.ORDER_API' must be declared
A misspelt variable in an anonymous block
Not reproduced here: no Oracle Database is installed for this site. The layout follows the PLS-00201 example in Oracle's PL/SQL Language Reference; the column numbers are illustrative. Unquoted names are shown in capitals because PL/SQL treats them as upper case.
DECLARE
v_total NUMBER;
BEGIN
v_totl := 10;
END;
/
ORA-06550: line 4, column 3: PLS-00201: identifier 'V_TOTL' must be declared ORA-06550: line 4, column 3: PL/SQL: Statement ignored
How to prevent it
For code that uses objects in other schemas, grant the needed privileges directly to the schema that owns the code, record those grants in your deployment scripts, and qualify names or create synonyms deliberately. Compile and check USER_ERRORS in every deployment.
Avoid quoted identifiers, and anchor variables with %TYPE so a misspelt column shows up as a clear error at compile time.
Common questions
Why does PLS-00201 say the object is not declared when it exists?
Because you cannot see it. Oracle reports a missing privilege the same way as a missing object, for security. Most often the privilege was granted through a role, and roles are not enabled inside stored procedures, functions, packages, triggers and views.
It works in an anonymous block but not in my procedure. Why?
An anonymous block runs with your session's enabled roles. A stored definer's-rights unit runs with only its owner's direct privileges and PUBLIC. Grant the privilege directly to the procedure's owner and recompile.
What is the difference between PLS-00201 and PLS-00302?
PLS-00201 means the name itself cannot be resolved. PLS-00302 "component must be declared" means the first part resolved (for example a package) but the member after the dot was not found or is not in the package specification.
Learn more on CodeWithSQL
Official documentation
- PLS-00201 (Oracle Database Error Messages)
- Invoker's rights and definer's rights (Oracle PL/SQL Language Reference 19c)
- Scope and visibility of identifiers (Oracle PL/SQL Language Reference 19c)
- ALL_TAB_PRIVS (Oracle Database Reference 19c)
Last technically reviewed 24 October 2026; examples and diagnostics run on Oracle Database Error Messages reference (26ai, 21c and 19c); not run locally. Messages and explanations follow Oracle's Database Error Messages reference; no Oracle Database was available, so the examples were not run locally.