ORA-04068 is raised when a session calls a package whose body was recompiled after the session started using it. A package with package-level variables keeps their values per session, its state. When a new version of the body is compiled, that state no longer fits, so Oracle discards it and reports ORA-04068 on the next call. It is common right after a deployment. The call after the error works, with fresh state.
Reproduce the Error
The error needs two sessions. First, a package that keeps a running total:
Example:
create or replace package demo_counter_pkg is
procedure add (p_n number);
procedure show;
end;
/
create or replace package body demo_counter_pkg is
g_total number := 0; -- package state, kept per session
procedure add (p_n number) is begin g_total := g_total + p_n; end;
procedure show is begin dbms_output.put_line('Total: ' || g_total); end;
end;
/Session 1 adds to the total, then waits 20 seconds and calls the package twice more:
Example:
-- session 1: builds up package state, then calls again after a recompile set serveroutput on exec demo_counter_pkg.add(5) exec demo_counter_pkg.show exec dbms_session.sleep(20) exec demo_counter_pkg.show set serveroutput on exec demo_counter_pkg.show
While it waits, session 2 deploys a new version of the body:
Example:
-- session 2, meanwhile: a new version of the package body is deployed
create or replace package body demo_counter_pkg is
g_total number := 0;
procedure add (p_n number) is begin g_total := g_total + p_n; end;
procedure show is begin dbms_output.put_line('Total now: ' || g_total); end;
end;
/Output of session 1:
PL/SQL procedure successfully completed. Total: 5 PL/SQL procedure successfully completed. PL/SQL procedure successfully completed. BEGIN demo_counter_pkg.show; END; * ERROR at line 1: ORA-04068: existing state of packages has been discarded ORA-04061: existing state of package body "NIMBUS.DEMO_COUNTER_PKG" has been invalidated ORA-04065: not executed, altered or dropped package body "NIMBUS.DEMO_COUNTER_PKG" ORA-06508: PL/SQL: could not find program unit being called: "NIMBUS.DEMO_COUNTER_PKG" ORA-06512: at line 1 Total now: 0 PL/SQL procedure successfully completed.
- The first call after the recompile fails with ORA-04068, followed by ORA-04061, ORA-04065, and ORA-06508.
- The next call runs the new code, with the total back at 0: the state of 5 is gone.
- Discarding package state also resets DBMS_OUTPUT's settings for the session, so the script turns SERVEROUTPUT on again.
Fix: Keep State Out of the Package
A package without package-level variables has no state to discard. The same test with such a package:
Example:
-- a package without package-level variables has no state to discard
create or replace package demo_counter_pkg is
function with_fee (p_amount number) return number;
end;
/
create or replace package body demo_counter_pkg is
function with_fee (p_amount number) return number is
begin
return p_amount + 25;
end;
end;
/Session 1 calls it, waits, and calls again:
Example:
-- session 1: calls the stateless package before and after a recompile select demo_counter_pkg.with_fee(100) as total from dual; exec dbms_session.sleep(20) select demo_counter_pkg.with_fee(100) as total from dual;
Session 2 changes the fee in the meantime:
Example:
-- session 2, meanwhile: a new version of the body, with a new fee
create or replace package body demo_counter_pkg is
function with_fee (p_amount number) return number is
begin
return p_amount + 30;
end;
end;
/Output of session 1:
TOTAL
________
125
PL/SQL procedure successfully completed.
TOTAL
________
130No error: the second call simply runs the new code, 125 before and 130 after.
Other Fixes
- PRAGMA SERIALLY_REUSABLE makes state last only for one call, so there is nothing kept to discard.
- Keep values that must last in a table or an application context instead of package variables.
- Edition-based redefinition lets sessions finish on the old code while new sessions use the new one.
- Applications with connection pools can catch ORA-04068 and repeat the call once.
Related Guides
- How to Use PRAGMA SERIALLY_REUSABLE in PL/SQL
- How to Fix ORA-06508: PL/SQL: Could Not Find Program Unit Being Called in Oracle
Conclusion
ORA-04068 means a package's session state was discarded because the package was recompiled. The next call works; to avoid the error, keep state out of packages, use SERIALLY_REUSABLE or edition-based redefinition, or retry the call once.
