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.

Get more Vinish.dev tutorials on Google

See my articles more often when you search Google.

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