How to Fix ORA-04068: Existing State of Packages Has Been Discarded in Oracle

Reproduce ORA-04068 with two sessions, see why package state is discarded after a recompile, and design packages that avoid it.

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
________
     130

No 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

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.

Vinish Kapoor
Vinish Kapoor

An Oracle ACE, author of four books on Oracle APEX, SQL and PL/SQL, and Oracle Forms, and a software developer building Oracle database applications since 2001.

guest

0 Comments
Oldest
Newest Most Voted