- Error code
- PLS-00306
- 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-00306 means a call to a procedure or function does not match any declaration of it: there are too many or too few arguments, an argument has an incompatible type, or no overloaded version fits.
When the PL/SQL compiler meets a call, it looks for a declaration with that name, first in the current scope and then in enclosing scopes, and checks that the parameter lists match: every required formal parameter (one without a default) must have an actual argument, and each argument must be of a compatible type. If no declaration matches, it reports PLS-00306 with the subprogram name. Oracle's action is to check the spelling and declaration of the subprogram, that the call is correct, that the parameters are of the right data type, and that the declaration is placed correctly in the block structure.
The message names the subprogram but not which argument is wrong, so compare the call with the declaration argument by argument. For a stored procedure, ALL_ARGUMENTS lists the declared parameters (one set per overload). Calls from applications through a driver are compiled as small anonymous blocks, so a wrong number of bind parameters there produces the same error under ORA-06550.
Common causes
- A required parameter is missing, or an extra argument is passed, often after the procedure's parameter list was changed and callers were not.
- An argument has an incompatible type: a record, collection or object where a scalar is expected, or the other way round, or a value of a different user-defined type with the same shape.
- The subprogram is overloaded and the argument types match none of the versions, as in Oracle's SWAP example, where a nested procedure of the same name hides the one meant.
- Named notation uses a parameter name the subprogram does not have, so the call cannot be matched to its parameter list.
- An application calls a stored procedure with a different number of bind parameters from its declaration.
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.
List the declared parameters
For a packaged subprogram, filter on package_name too. Oracle notes that since 12.1.0.2 this view omits subprograms that have no arguments at all.
SELECT overload, position, argument_name, data_type, in_out, defaulted,
type_owner, type_name
FROM all_arguments
WHERE owner = 'SHOP'
AND object_name = 'ADD_CUSTOMER'
AND package_name IS NULL -- or = 'CUSTOMER_API' for a package
ORDER BY overload, sequence; Each parameter in order with its type and mode. defaulted = Y marks optional parameters; a non-NULL overload column means there are several versions. Position 0 is a function's return value.
Did the declaration change recently?
SELECT object_name, object_type, status, last_ddl_time
FROM all_objects
WHERE owner = 'SHOP'
AND object_name IN ('ADD_CUSTOMER', 'CUSTOMER_API')
ORDER BY object_type; A recent last_ddl_time on the called unit, with callers that now fail, suggests the parameter list changed and the callers were not updated.
Which units call it?
SELECT owner, name, type
FROM all_dependencies
WHERE referenced_owner = 'SHOP'
AND referenced_name = 'ADD_CUSTOMER'
ORDER BY owner, name; Every stored unit that depends on the subprogram, which are the callers to review after a signature change.
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.
Make the call match the declaration, using named notation
Changes schemaPass every required parameter with the right type. Named notation (p_email => ...) makes the match explicit, lets you omit any optional parameter, and keeps working if parameters are reordered; Oracle's reference notes that with positional notation the wrong order can cause problems that are hard to detect.
CREATE OR REPLACE PROCEDURE shop.register_web_user (p_name IN VARCHAR2, p_email IN VARCHAR2)
IS
BEGIN
shop.add_customer(p_name => p_name,
p_email => LOWER(TRIM(p_email)));
END;
/
Add new parameters with a default so existing calls still match
Changes schemaWhen you extend a procedure, give the new IN parameter a default value. It is then optional, and calls written before the change keep compiling.
CREATE OR REPLACE PROCEDURE shop.add_customer (
p_name IN VARCHAR2,
p_email IN VARCHAR2,
p_marketing IN VARCHAR2 DEFAULT 'N') -- new, optional
IS
BEGIN
INSERT INTO shop.customers (full_name, email, marketing_opt_in)
VALUES (p_name, p_email, p_marketing);
END;
/
Pass a value of the declared type
Changes schemaIf the procedure expects a record of a given type, build that record; if it expects a scalar, pass the field. Declaring variables with %TYPE and %ROWTYPE of the same table the procedure uses keeps types aligned.
Examples
A required parameter is missing
Not reproduced here: no Oracle Database is installed for this site. The layout follows the PLS-00306 example in Oracle's PL/SQL Language Reference (subprogram invocation resolution); names and positions are illustrative.
CREATE OR REPLACE PROCEDURE add_customer (p_name IN VARCHAR2, p_email IN VARCHAR2) IS
BEGIN
INSERT INTO customers (full_name, email) VALUES (p_name, p_email);
END;
/
BEGIN
add_customer('Sara Ahmed'); -- p_email has no default
END;
/
ORA-06550: line 2, column 3: PLS-00306: wrong number or types of arguments in call to 'ADD_CUSTOMER' ORA-06550: line 2, column 3: PL/SQL: Statement ignored
A record passed where a number is expected
Not reproduced here: no Oracle Database is installed for this site. The message is from Oracle's error reference and the layout from its documented example; names and positions are illustrative. The message names only the subprogram, so compare the argument with ALL_ARGUMENTS to see that it expects a NUMBER.
-- shop.order_api.ship(p_order_id IN NUMBER)
DECLARE
r orders%ROWTYPE;
BEGIN
SELECT * INTO r FROM orders WHERE id = 1001;
shop.order_api.ship(r); -- should be r.id
END;
/
ORA-06550: line 6, column 3: PLS-00306: wrong number or types of arguments in call to 'SHIP' ORA-06550: line 6, column 3: PL/SQL: Statement ignored
How to prevent it
Use named notation for calls with more than one or two parameters, give new parameters defaults, and check ALL_DEPENDENCIES for callers before changing a signature. Keep public signatures in package specifications stable and add overloads deliberately.
Recompile dependent code and check USER_ERRORS in every deployment, so a mismatched call fails at deploy time rather than when a user first runs it.
Common questions
How do I fix PLS-00306 wrong number or types of arguments?
List the subprogram's parameters from ALL_ARGUMENTS (or its source), then compare the call argument by argument: count, order, and type of each value. Add the missing argument, remove the extra one, or pass a value of the declared type.
Why does the message not say which argument is wrong?
The compiler looks for any declaration that matches the whole call and reports only that none was found. With overloads there may be several candidates, so it cannot point to one argument.
Can I leave out parameters?
Only optional ones, that is IN parameters declared with a default. With positional notation you can omit only trailing optional parameters; with named notation you can omit any of them.
Learn more on CodeWithSQL
Official documentation
- PLS-00306 (Oracle Database Error Messages)
- Subprogram invocation resolution (Oracle PL/SQL Language Reference 19c)
- Subprogram parameters, notation and defaults (Oracle PL/SQL Language Reference 19c)
- ALL_ARGUMENTS (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.