Category: Uncategorized

  • Oracle Database 19c July 2026 RU Patching – Upgrade from 19.31 to 19.32 on Linux

    الحمد لله — This post documents a real Oracle Database 19c patching activity on a Linux x86-64 environment, progressing from 19.31 to 19.32 using the July 2026 Combo Patch. The activity included precheck validation, binary patching, datapatch execution, and post-patch verification with actual command outputs.

    Introduction

    This article documents the steps followed to patch an Oracle Database 19c environment from 19.31 to 19.32 using the July 2026 Database and OJVM Release Update Combo Patch on Linux x86-64.

    The patches applied were:

    Patch 39618649
    Combo of OJVM Component Release Update 19.32.0.0.260721
    + Database Jul 2026 Release Update 19.32.0.0.260721
    
    Component patches:
    39472050 - Database Release Update 19.32.0.0.260721
    39222882 - Oracle JavaVM Component Release Update 19.32.0.0.260721

    Pre-Patching Validation

    1. Verify Current Database Patch Level

    First, verify the current patches installed in the Oracle Home:

    $ $ORACLE_HOME/OPatch/opatch lspatches

    The environment was running the following baseline before July patching:

    38906621;OJVM RELEASE UPDATE: 19.31.0.0.260421
    39034528;Database Release Update : 19.31.0.0.260421
    29585399;OCW RELEASE UPDATE 19.3.0.0.0

    Patching objective:

    • Database RU: 19.31 → 19.32 (39034528 → 39472050)
    • OJVM RU: 19.31 → 19.32 (38906621 → 39222882)

    6. Run DB RU Conflict Check

    Before applying the Database RU, validate for conflicting one-off patches:

    $ cd 39618649/39472050
    $ opatch prereq CheckConflictAgainstOHWithDetail -ph ./
    
    Prereq "checkConflictAgainstOHWithDetail" passed.
    
    OPatch succeeded.

    ✓ No conflicting one-off patch was identified for the DB RU 39472050.

    7. Run OJVM RU Conflict Check

    Perform the same validation for the OJVM RU:

    $ cd 39618649/39222882
    $ opatch prereq CheckConflictAgainstOHWithDetail -ph ./
    
    Prereq "checkConflictAgainstOHWithDetail" passed.
    
    OPatch succeeded.

    ✓ No conflicting one-off patch was identified for the OJVM RU 39222882.

    Post-Patching Results

    OPatch Inventory Verification

    $ $ORACLE_HOME/OPatch/opatch lspatches
    
    39222882;OJVM RELEASE UPDATE: 19.32.0.0.260721
    39472050;Database Release Update : 19.32.0.0.260721
    29585399;OCW RELEASE UPDATE 19.3.0.0.0
    
    OPatch succeeded.

    Patch progression:

    • OJVM RU: 38906621 (19.31) → 39222882 (19.32) ✓
    • Database RU: 39034528 (19.31) → 39472050 (19.32) ✓
    • OCW: 29585399 (unchanged) ✓

    Component Registry Status

    All major database components are VALID after patching:

    CATALOG         VALID
    CATEGORY        VALID
    CATJAVA         VALID
    CATOJAVA        VALID
    JAVAVM          VALID
    XML             VALID
    XDB             VALID

    Database and PDB Status

    SQL> select name, open_mode, database_role from v$database;
    
    NAME            OPEN_MODE       DATABASE_ROLE
    ----------      -----------     ----------------
    PRODDB          READ WRITE      PRIMARY
    
    SQL> show pdbs;
    
        CON_ID CON_NAME                 OPEN_MODE  RESTRICTED
    ---------- ---------------------- ---------- ----------
             2 PDB$SEED                 READ ONLY  NO
             3 APPPDB                   READ WRITE NO
             4 ARCHPDB                  READ WRITE NO

    ✓ Database and all PDBs are open and operational.

    SQL Patch Registry

    Both 19.32 patches applied successfully to CDB and APPPDB PDB:

    PATCH_ID      ACTION     STATUS          DESCRIPTION
    -----------   ---------- --------------- ----------------------------------
    39222882      APPLY      SUCCESS         OJVM RU 19.32.0.0.260721
    39472050      APPLY      SUCCESS         Database RU 19.32.0.0.260721

    Note: During the 19.32 OJVM update, the previous 19.31 OJVM patch (38906621) may be recorded as ROLLBACK SUCCESS, followed by successful application of OJVM RU 39222882. This is normal and expected during the RU transition — it is not an indication of a patching failure.

    Invalid Objects Validation

    Post-patch invalid objects count: 83 (unchanged from pre-patch baseline)

    ✓ Invalid object count matches pre-patch baseline. No new invalids introduced by 19.32 RU.

    oradism Permissions Restored

    $ ls -l $ORACLE_HOME/bin/oradism
    -rwsr-x---. 1 root oinstall 147848 May  5 12:25 /u01/app/oracle/product/19c/db_1/bin/oradism

    ✓ Permissions correctly restored to original state (root:oinstall 4750).

    Rollback Plan

    Important: Before executing any rollback, always:

    • Verify the exact version from the patch component README
    • Follow the documented rollback sequence from the README
    • Test in a non-production environment first
    • Obtain explicit approval from your database administration team or management

    If the 19.32 RU must be rolled back, the procedure generally follows this sequence (consult the specific README for patches 39472050 and 39222882 for the authoritative step-by-step guidance):

    1. Shut down the database and listener
    2. Revert the OJVM RU first, then the Database RU (reverse order of application)
    3. Start the database in restricted mode to verify compatibility
    4. Run datapatch to revert SQL patches: ./datapatch -verbose
    5. Verify patch registry and OPatch inventory reflect the reverted state
    6. Open the database normally and run post-revert health checks

    Always retain a clean, tested backup of the Oracle Home taken immediately before patching. This allows for rapid restoration if rollback becomes necessary.

    Key Takeaways

    A reliable Oracle Database RU patching activity is more than running opatch apply twice. A structured approach includes:

    • Capture existing state: Patch inventory, SQL patch registry, invalid objects, database role, PDB status, and oradism permissions before making any changes.
    • Validate prerequisites: Run conflict checks on both component patches and ensure OPatch is at the recommended version.
    • Follow the documented sequence: Binary patches in the correct order, then startup, then datapatch.
    • Verify at each step: Check OPatch inventory after binary patching, verify component registry after startup, and confirm datapatch success via the SQL registry.
    • Compare against baseline: Invalid objects, registry status, and listener configuration should match pre-patch evidence.
    • Plan for rollback: Maintain a clean backup and understand the documented rollback procedure from the official patch README before starting.

    Oracle Database 19c was successfully upgraded from the 19.31 RU level to the July 2026 19.32 RU level, including OJVM, with successful binary patching, SQL patching, and post-patch health validation.

  • Oracle EBS WebLogic: Troubleshooting Security:090220 Rule 2 Connection Rejection

    You receive a call: WebLogic requests are being rejected.

    The error appears in the logs:

    [Socket:000445]Connection rejected, filter blocked Socket,
    weblogic.security.net.FilterException:
    [Security:090220]rule 2

    At first, you might start checking WebLogic authentication, AdminServer credentials, or database connectivity.

    Don’t start there.

    The exception is already giving you a very strong clue about where to investigate.

    The Error Tells the Story

    The important part is:

    weblogic.security.net.FilterException
    [Security:090220]rule 2

    Oracle documents BEA-090220 as:

    A connection filter rule denied access.

    In other words, WebLogic is rejecting the connection because of a configured connection-filter rule.

    This is different from an authentication failure.

    The request is reaching the WebLogic server, and the connection filter is evaluating the incoming connection.

    What Is a WebLogic Connection Filter?

    WebLogic connection filters provide a network-level access-control layer.

    They can be used to control which clients are permitted to connect to a WebLogic Server instance. Oracle describes connection filters as an additional security layer that can restrict access at the network level.

    A simplified flow looks like this:

    Client
       |
       v
    WebLogic Listener
       |
       v
    Connection Filter
       |
       +---- ALLOW ----> Continue processing
       |
       +---- DENY -----> Connection rejected

    This is why an error such as:

    Connection rejected, filter blocked Socket

    is so useful during troubleshooting.

    Understanding Security:090220 Rule 2

    This is where we need to be precise.

    WebLogic evaluates connection-filter rules in the order in which they are configured.

    The first matching rule determines whether the connection is allowed or denied. If no rule matches, the connection is permitted by the default filter implementation.

    For example:

    Rule 1: 192.0.2.11 * * allow
    Rule 2: 192.0.2.12 * * allow
    Rule 3: 0.0.0.0/0 * * deny

    If a connection matches Rule 3, WebLogic reports:

    [Security:090220]rule 3

    Therefore:

    rule 2 identifies the connection-filter rule associated with the rejection reported by WebLogic. Always inspect the actual configured rule sequence rather than assuming it is the catch-all deny rule.

    Where Is the Configuration?

    For Oracle E-Business Suite Release 12.2, the WebLogic connection-filter configuration can be found in:

    $DOMAIN_HOME/config/config.xml

    Oracle’s EBS documentation shows the connection-filter configuration in this file.

    For example:

    <connection-filter>weblogic.security.net.ConnectionFilterImpl</connection-filter>
    
    <connection-filter-rule>192.0.2.11 * * allow</connection-filter-rule>
    
    <connection-filter-rule>192.0.2.12 * * allow</connection-filter-rule>
    
    <connection-filter-rule>0.0.0.0/0 * * deny</connection-filter-rule>

    In an EBS environment you may also see an EBS-specific connection-filter implementation, such as:

    <connection-filter>oracle.apps.ad.tools.configuration.wls.filter.EBSConnectionFilterImpl</connection-filter>

    If that is what your environment is using, don’t replace the filter class just because you are troubleshooting a rule. Focus on the configured rules.

    Check the Rules Before Changing Anything

    First inspect the actual configuration:

    cd $DOMAIN_HOME/config
    
    grep -n -A10 -B5 "connection-filter" config.xml

    You want to establish:

    • Which connection-filter implementation is configured?
    • What are the connection-filter rules?
    • Which source IP is making the connection?
    • Which rule is actually denying the connection?
    • Is the source IP supposed to be allowed?

    This is much better than immediately changing the filter to allow.

    Always Back Up config.xml

    Before making any manual configuration change:

    cd $DOMAIN_HOME/config
    
    cp -ip config.xml config.xml_$(date +%Y%m%d_%H%M%S).bak

    If this is an EBS environment, also consider the run/patch filesystem implications before making a change that needs to persist through online patching. Oracle’s EBS documentation notes that configuration changes on the run filesystem are propagated to the patch filesystem during fs_clone.

    Don’t Confuse This With Basic Authentication

    While reviewing config.xml, you may encounter:

    <enforce-valid-basic-auth-credentials>
        false
    </enforce-valid-basic-auth-credentials>

    It is tempting to associate this with every WebLogic security-related error.

    But BEA-090220 specifically indicates that a connection-filter rule denied access.

    Therefore, for this particular error, the first investigation should be:

    Security:090220
           ↓
    Connection Filter
           ↓
    Connection Filter Rules
           ↓
    Source IP / Port / Protocol

    rather than Basic Authentication.

    A Typical Configuration

    Oracle’s EBS documentation provides examples such as:

    <connection-filter-rule>192.0.2.11 * * allow</connection-filter-rule>
    
    <connection-filter-rule>192.0.2.12 * * allow</connection-filter-rule>
    
    <connection-filter-rule>192.0.2.100 * 17001 allow https</connection-filter-rule>
    
    <connection-filter-rule>0.0.0.0/0 * * deny</connection-filter-rule>

    The final rule:

    0.0.0.0/0 * * deny

    acts as a catch-all deny.

    Oracle specifically documents this pattern: allow the required sources first, then use 0.0.0.0/0 * * deny as the final rule so that all other sources are rejected.

    The Incident Scenario

    In our case, the error was:

    [Socket:000445]Connection rejected, filter blocked Socket,
    weblogic.security.net.FilterException:
    [Security:090220]rule 2

    During the investigation, we reviewed the WebLogic configuration and traced the rejection back to the connection-filter rules.

    The important distinction was:

    WebLogic is running
            |
            v
    Request reaches WebLogic
            |
            v
    Connection filter evaluates request
            |
            v
    Configured rule denies connection
            |
            v
    Security:090220

    That changed the direction of the investigation immediately.

    Resolution

    Once the offending rule has been identified, there are two approaches.

    Option 1 — Correct the Allow Rule

    This is the preferred approach.

    For example, if the trusted WebLogic client is:

    192.0.2.50

    the configuration could contain:

    <connection-filter-rule>192.0.2.50 * * allow</connection-filter-rule>
    
    <connection-filter-rule>0.0.0.0/0 * * deny</connection-filter-rule>

    The important point is that the allow rule must appear before the catch-all deny rule.

    Option 2 — Temporary Troubleshooting Workaround

    In a controlled troubleshooting situation, changing:

    0.0.0.0/0 * * deny

    to:

    0.0.0.0/0 * * allow

    can be used to confirm that the connection filter is the cause of the problem.

    However, this effectively removes the intended network restriction.

    So: Use this as a diagnostic/workaround step, not as the preferred permanent production configuration.

    Oracle’s documented security model is to allow the required sources and retain a final deny rule.

    If Manually Editing config.xml

    If you are manually modifying the domain configuration rather than using the WebLogic Administration Console, perform the change under your environment’s standard configuration-management procedure and ensure the Administration Server is not concurrently modifying the file.

    For a controlled manual change, the practical sequence is:

    Stop AdminServer
          |
          v
    Backup config.xml
          |
          v
    Review current connection-filter rules
          |
          v
    Make the required change
          |
          v
    Validate config.xml
          |
          v
    Start AdminServer
          |
          v
    Monitor logs
          |
          v
    Retest the connection

    Oracle also supports configuring connection filters through the WebLogic Administration Console and then activating the configuration and restarting as required.

    Troubleshooting Decision Tree

    When you encounter:

    [Socket:000445]Connection rejected, filter blocked Socket
    weblogic.security.net.FilterException
    [Security:090220]rule N

    use this approach:

                     WebLogic Request
                           |
                           v
                  WebLogic reachable?
                           |
                          YES
                           |
                           v
                 Check exact exception
                           |
                           v
              weblogic.security.net
                 FilterException?
                           |
                          YES
                           |
                           v
                  Security:090220?
                           |
                          YES
                           |
                           v
           Review connection-filter rules
                           |
                           v
              Identify rule N
                           |
                           v
            Identify source IP/port/protocol
                           |
                           v
              Does the rule allow it?
                     /          \
                   YES          NO
                    |            |
                    v            v
            Investigate next   Correct the
                 layer          filter rule

    Key Takeaways

    1. Read the exception literallyFilterException is a major clue.
    2. Security:090220 means a connection-filter rule denied access — Oracle explicitly documents BEA-090220 this way.
    3. Rule ordering matters — The first matching rule determines the result.
    4. rule 2 is not automatically the catch-all deny — Check the actual rule list before making assumptions.
    5. 0.0.0.0/0 * * deny is normally a catch-all restriction — It should generally come after the required allow rules.
    6. Don’t use a global allow as the permanent fix — If the issue is caused by a missing source IP rule, add the required source rather than permanently opening the filter.

    Final Thought

    One of the most useful troubleshooting skills in middleware administration is learning to read the error as a diagnostic path.

    Consider the original message:

    [Socket:000445]
    Connection rejected,
    filter blocked Socket,
    weblogic.security.net.FilterException:
    [Security:090220]rule 2

    Break it down:

    Connection rejected
            ↓
    Filter blocked Socket
            ↓
    WebLogic Connection Filter
            ↓
    BEA/Security 090220
            ↓
    Connection-filter rule denied access
            ↓
    Check the actual rule identified by the error

    Instead of treating it as another generic WebLogic failure, the error points us directly toward the connection-filter configuration.

    Read the error carefully. Sometimes the error message has already told you where the problem is.

  • Troubleshooting Oracle EBS R12.1 txkCfgUtlfileDir.pl: APPS Lockouts, Missing AppsUtil JRE & UTL_FILE_DIR Synchronization

    Alhamdulillah.

    Introduction

    While working on an Oracle E-Business Suite R12.1 environment running on Oracle Database 19c, I encountered a failure while configuring the database-side UTL_FILE_DIR replacement using txkCfgUtlfileDir.pl.

    The script repeatedly reported:

    ERRORMSG: Invalid APPS database user credentials.
    ERRORCODE = 1 ERRORCODE_END

    At first glance, this looked like a straightforward APPS password problem.

    It wasn’t.

    The investigation eventually uncovered two separate contributing factors:

    • Issue 1: The APPS account was being locked by repeated authentication attempts from an external application.
    • Issue 2: The TXK utility expected a JRE component that was missing from the AppsUtil directory structure.

    These were independent issues discovered during different phases of the troubleshooting investigation. After resolving the APPS lockout and verifying the JRE availability, the UTL_FILE_DIR synchronization proceeded to completion: directory objects → setUtlFileDir → syncUtlFileDir → FND_CONC_CLONE.SETUP_CLEAN → Database AutoConfig.

    This post documents the investigation and the commands used.

    1. Environment

    The database environment was:

    Oracle E-Business Suite R12.1
    Oracle Database 19c
    Database CDB : SRCDB
    PDB          : TESTDB
    Listener     : 1522
    Service      : ebs_service

    The ORACLE_HOME was:

    ORACLE_HOME=$ORACLE_BASE/TESTDB/db/tech_st/19.3.0.0

    The EBS database context file was:

    CONTEXT_FILE=$ORACLE_HOME/appsutil/TESTDB_dbctx.xml

    The environment was loaded with:

    cd $ORACLE_HOME
    . ./TESTDB_dbctx.env

    Validation:

    echo "ORACLE_SID=$ORACLE_SID"
    echo "ORACLE_HOME=$ORACLE_HOME"
    echo "TNS_ADMIN=$TNS_ADMIN"
    echo "CONTEXT_FILE=$CONTEXT_FILE"

    Expected values:

    ORACLE_SID=TESTDB
    ORACLE_HOME=$ORACLE_BASE/TESTDB/db/tech_st/19.3.0.0
    TNS_ADMIN=$ORACLE_HOME/network/admin/TESTDB_dbctx
    CONTEXT_FILE=$ORACLE_HOME/appsutil/TESTDB_dbctx.xml

    2. Initial txkCfgUtlfileDir.pl Failure

    The initial command was:

    perl $ORACLE_HOME/appsutil/bin/txkCfgUtlfileDir.pl \
    -contextfile=$CONTEXT_FILE \
    -oraclehome=$ORACLE_HOME \
    -outdir=$ORACLE_HOME/appsutil/log \
    -mode=getUtlFileDir

    The script failed with:

    FUNCTION: main::validateAppsSchemaCredentials
    ERRORMSG: Invalid APPS database user credentials.
    ERRORCODE = 1 ERRORCODE_END

    The context file itself was found successfully:

    Context file:
    $ORACLE_HOME/appsutil/TESTDB_dbctx.xml exists.

    So the failure was occurring during APPS credential validation.

    3. Validate the PDB

    Because this was a multitenant database, I first verified the PDB state.

    SHOW PDBS;

    Output:

    CON_ID CON_NAME    OPEN MODE   RESTRICTED
    ------ ----------- ----------- ----------
    2      PDB$SEED    READ ONLY   NO
    3      TESTDB      READ WRITE  NO

    Then:

    ALTER SESSION SET CONTAINER=TESTDB;

    The PDB was open read/write, so the next step was to validate the APPS account.

    4. APPS Account Investigation

    Initially, the APPS account showed as open after an unlock:

    ALTER USER APPS ACCOUNT UNLOCK;

    Verification:

    SELECT username,
           account_status,
           lock_date
    FROM dba_users
    WHERE username = 'APPS';

    At one point:

    APPS    OPEN

    However, the TXK utility continued to report invalid APPS credentials.

    The most useful clue came from the TXK-generated diagnostic log:

    cat $ORACLE_HOME/appsutil/log/TXK_UTIL_DIR_*/validate_apps_password.log

    The log showed:

    Connected to an idle instance.
    ERROR:
    ORA-28000: The account is locked.

    This was much more specific than the generic TXK error. The failure was occurring at the database authentication layer, not at the password validation level.

    5. Understanding the TXK Workflow

    Rather than treating the generic TXK error at face value, I inspected txkCfgUtlfileDir.pl to understand how the utility validates the APPS credentials.

    The script constructs the database connection using the APPS credentials from the EBS configuration and performs the validation through SQL*Plus. The detailed validate_apps_password.log showed ORA-28000, confirming that the failure was occurring at the database authentication layer.

    6. Verify Context Configuration

    The context file contained:

    grep -n -iE 's_apps_user|s_dbSid|s_tools_twotask|s_dbService' \
    $CONTEXT_FILE

    Relevant values:

    s_dbSid       = TESTDB
    s_dbService   = ebs_service
    s_apps_user   = apps

    The database SID, service and listener port were also checked in the context configuration:

    grep -n -iE 's_dbSid|s_dbService|s_dbport' \
    $CONTEXT_FILE

    Result:

    s_dbSid       = TESTDB
    s_dbService   = ebs_service
    s_dbport      = 1522

    These values were consistent with the environment.

    7. Verify TNS Connectivity

    The EBS TNS entry was properly configured for the PDB service.

    export TNS_ADMIN=$ORACLE_HOME/network/admin/TESTDB_dbctx

    Then:

    tnsping TESTDB

    Result:

    Used TNSNAMES adapter to resolve the alias
    Attempting to contact ...
    OK (0 msec)

    Therefore: TNS resolution and listener connectivity were not the problem.

    8. Important Discovery: APPS Account Was Being Locked

    At another point during testing, the account showed:

    USERNAME        ACCOUNT_STATUS
    --------------- -------------------------
    APPS            LOCKED(TIMED)

    The account was unlocked:

    ALTER USER APPS ACCOUNT UNLOCK;

    Then a direct connection succeeded:

    sqlplus apps@TESTDB
    
    SHOW USER;
    USER is "APPS"

    This confirmed that the APPS credentials being used for the direct SQL*Plus connection were valid at that point. However, subsequent attempts to run the TXK utility showed the account locked again:

    ORA-28000: The account is locked.

    This pattern indicated that something was repeatedly attempting authentication with invalid credentials, causing the account to lock after a number of failed attempts. The generic TXK error message “Invalid APPS database user credentials” did not hint at this root cause.

    9. SplashBI Was Contributing to the Lockout

    During the investigation, SplashBI sessions were identified as contributing to repeated APPS authentication attempts, and stale credentials were suspected.

    Those sessions were stopped/killed before continuing with the TXK procedure.

    This was a critical troubleshooting lesson:

    Do not repeatedly unlock APPS and rerun the TXK utility while another application is continuously attempting to authenticate with stale APPS credentials.

    Doing so simply creates another lockout cycle. After the interfering sessions were stopped, APPS authentication could be validated successfully, and the TXK procedure proceeded.

    10. A Second Prerequisite Issue: Missing AppsUtil JRE

    This was a separate issue discovered during the later stages of the TXK workflow. An earlier execution of syncUtlFileDir had shown:

    FUNCTION: main::getJavaCmd
    
    ERRORMSG:
    Invalid JDK TOP:
    $ORACLE_HOME/appsutil/jre/bin/java

    I checked:

    ls -ld $ORACLE_HOME/appsutil/jre

    and found:

    No such file or directory

    However, the AppsUtil clone area contained a valid JRE:

    ls -ld $ORACLE_HOME/appsutil/clone/jre

    and:

    ls -l $ORACLE_HOME/appsutil/clone/jre/bin/java

    The Java executable was present. Validation:

    $ORACLE_HOME/appsutil/clone/jre/bin/java -version
    
    java version "1.8.0_451"
    Java(TM) SE Runtime Environment

    11. Backup Before Correcting AppsUtil

    Before making the AppsUtil change, a backup was taken:

    cd $ORACLE_HOME/appsutil
    
    tar -czf $ORACLE_BASE/TESTDB/appsutil_pre_jre_fix_$(date +%Y%m%d_%H%M%S).tar.gz \
        TESTDB_dbctx.xml \
        txkSetCfgCDB.env \
        clone/jre

    The backup was verified:

    ls -lh $ORACLE_BASE/TESTDB/appsutil_pre_jre_fix_*.tar.gz
    
    -rw-r--r-- 1 oracle dba 46M Aug 18 11:32 appsutil_pre_jre_fix_20260818_113218.tar.gz

    This provided a rollback point before modifying the directory structure.

    12. Restore the Expected AppsUtil JRE

    The TXK source explicitly showed that getJavaCmd expected:

    $ORACLE_HOME/appsutil/jre/bin/java

    The existing valid JRE under clone/jre was copied to the expected location:

    cp -pR $ORACLE_HOME/appsutil/clone/jre \
           $ORACLE_HOME/appsutil/jre

    Validation:

    ls -ld $ORACLE_HOME/appsutil/jre
    ls -l $ORACLE_HOME/appsutil/jre/bin/java
    
    $ORACLE_HOME/appsutil/jre/bin/java -version
    java version "1.8.0_451"

    This restored the Java path expected by the TXK utility.

    13. Existing UTL_FILE_DIR Configuration

    An earlier execution had already generated:

    $ORACLE_HOME/dbs/TESTDB_utlfiledir.txt

    The original getUtlFileDir execution had failed during APPS credential validation when the account was locked. After resolving the APPS lockout and stopping the interfering authentication attempts, the TXK workflow was able to proceed. The existing configuration file from the previous successful run was available as a reference for the required filesystem paths.

    The paths included:

    $ORACLE_BASE/TESTDB/temp
    $APP_MOUNT/TESTDB/inst/apps/TESTDB_dbctx/appltmp
    $APP_MOUNT/TESTDB/apps/apps_st/comn/temp
    $ORACLE_BASE/TESTDB/db/tech_st/19.3.0.0/admin/po_terms
    $ORACLE_BASE/TESTDB/db/tech_st/temp/TESTDB

    14. Create the Directory Objects

    The TXK utility was then run in createDirObject mode for each required OS path.

    perl $ORACLE_HOME/appsutil/bin/txkCfgUtlfileDir.pl \
    -contextfile=$CONTEXT_FILE \
    -oraclehome=$ORACLE_HOME \
    -outdir=$ORACLE_HOME/appsutil/log \
    -mode=createDirObject

    The utility prompted for:

    Enter the APPS Password:
    Enter the SYSTEM Password:
    Enter the OS path for which directory object needs to be created:

    Each of the required paths completed with:

    Successfully Completed the script
    ERRORCODE = 0 ERRORCODE_END

    15. Run setUtlFileDir

    The next step was:

    perl $ORACLE_HOME/appsutil/bin/txkCfgUtlfileDir.pl \
    -contextfile=$CONTEXT_FILE \
    -oraclehome=$ORACLE_HOME \
    -outdir=$ORACLE_HOME/appsutil/log \
    -mode=setUtlFileDir

    The script returned:

    WARNING: Incorrect value s_applptmp detected on Apps Tier nodes.

    However:

    Successfully Completed the script
    ERRORCODE = 0 ERRORCODE_END

    Therefore the operation itself succeeded, while the s_applptmp issue was recorded as a warning for further review.

    16. Synchronize UTL_FILE_DIR

    The next documented step was:

    perl $ORACLE_HOME/appsutil/bin/txkCfgUtlfileDir.pl \
    -contextfile=$CONTEXT_FILE \
    -oraclehome=$ORACLE_HOME \
    -outdir=$ORACLE_HOME/appsutil/log \
    -mode=syncUtlFileDir \
    -skipautoconfig=yes

    This completed successfully:

    Successfully Completed the script
    ERRORCODE = 0 ERRORCODE_END

    At this point the TXK UTL_FILE_DIR synchronization portion was complete.

    17. Clean EBS Node Configuration

    The next database-side EBS step was:

    EXEC FND_CONC_CLONE.SETUP_CLEAN;
    
    COMMIT;

    Output:

    PL/SQL procedure successfully completed.
    
    Commit complete.

    Immediately afterward, querying FND_NODES returned:

    no rows selected

    This was expected at this point because SETUP_CLEAN removes the existing node registrations so that AutoConfig can rebuild them.

    18. Run Database AutoConfig

    Database AutoConfig was then executed from the database context directory:

    cd $ORACLE_HOME/appsutil
    sh adautocfg.sh

    The script prompted:

    Enter the APPS user password:

    The AutoConfig log was located at:

    $ORACLE_HOME/appsutil/log/TESTDB_dbctx/[timestamp]/adconfig.log

    The important output was:

    Context Value Management will now update the Context file
    
    Updating Context file...COMPLETED
    
    Attempting upload of Context file and templates to database...COMPLETED
    
    Updating rdbms version in Context file to db19
    Updating rdbms type in Context file to 64 bits
    
    Configuring templates from ORACLE_HOME ...
    
    AutoConfig completed successfully.

    This confirmed that the database AutoConfig completed successfully.

    19. Validate EBS Node Registration

    After AutoConfig completed successfully, the final validation was to confirm that the EBS node registrations had been recreated.

    SET LINES 200
    SET PAGES 50
    
    COLUMN node_name FORMAT A15
    COLUMN host_name FORMAT A30
    COLUMN status FORMAT A10
    COLUMN cp FORMAT A5
    COLUMN forms FORMAT A5
    COLUMN web FORMAT A5
    COLUMN admin FORMAT A5
    COLUMN db FORMAT A5
    COLUMN webhost FORMAT A30
    COLUMN last_update FORMAT A20
    
    ALTER SESSION SET NLS_DATE_FORMAT='DD-MON-YYYY HH24:MI:SS';
    
    SELECT node_name,
           host || '.' || domain host_name,
           DECODE(status,'Y','active','inactive') status,
           DECODE(support_cp,'Y','yes','no') cp,
           DECODE(support_forms,'Y','yes','no') forms,
           DECODE(support_web,'Y','yes','no') web,
           DECODE(support_admin,'Y','yes','no') admin,
           DECODE(support_db,'Y','yes','no') db,
           webhost,
           last_update_date
    FROM apps.fnd_nodes
    WHERE node_name != 'AUTHENTICATION'
    ORDER BY 7,1;

    Output:

    NODE_NAME       HOST_NAME                      STATUS     CP    FORMS WEB   ADMIN DB    WEBHOST                   LAST_UPDATE_DATE
    --------------- ------------------------------ ---------- ----- ----- ----- ----- ----- ------------------------- --------------------
    EBSNODE         [masked-hostname]              inactive   no    no    no    no    yes                           18-AUG-2026 12:50:45

    The node registration was successfully rebuilt with the database tier configuration active (DB = yes) and other tiers set to inactive pending app-tier AutoConfig execution.

    Root Cause: Two Independent Issues

    The investigation identified two distinct, independent issues that required separate solutions. This is important to understand because confusing the two would have masked the actual root cause in each case.

    Issue 1 — APPS Account Lockout (Database Authentication Layer)

    The TXK utility reported:

    Invalid APPS database user credentials.

    The detailed validation log showed:

    ORA-28000: The account is locked.

    The APPS account was repeatedly becoming LOCKED(TIMED) due to repeated authentication attempts. SplashBI sessions were identified as contributing to those attempts. This was resolved by stopping the interfering sessions and unlocking the APPS account.

    Issue 2 — Missing AppsUtil JRE (Environment/Configuration Layer)

    During the later TXK workflow, syncUtlFileDir encountered:

    Invalid JDK TOP:
    $ORACLE_HOME/appsutil/jre/bin/java

    The expected JRE path did not exist, while a valid JRE was available under:

    $ORACLE_HOME/appsutil/clone/jre

    This was resolved by copying the JRE to the expected AppsUtil location after taking a backup. This issue was completely independent of the APPS account lockout and would have persisted even if APPS had been unlocked from the start.

    Key lesson: Do not conflate unrelated failures during troubleshooting. Each issue required its own diagnosis and its own fix. Resolving one would not have solved the other.

    Troubleshooting Sequence

    Phase 1: APPS/TXK Troubleshooting

    1. Validate CDB/PDB state
    2. Validate EBS context configuration
    3. Validate TNS connectivity
    4. Check APPS account status
    5. Inspect validate_apps_password.log
    6. Identify repeated APPS authentication attempts
    7. Stop interfering SplashBI sessions
    8. Unlock APPS
    9. Validate direct APPS login

    Phase 2: TXK/UTL_FILE_DIR Configuration

    1. Verify AppsUtil JRE
    2. Take AppsUtil backup
    3. Restore expected appsutil/jre if required
    4. Create directory objects
    5. setUtlFileDir
    6. syncUtlFileDir -skipautoconfig=yes
    7. FND_CONC_CLONE.SETUP_CLEAN
    8. COMMIT
    9. Run Database AutoConfig
    10. Validate FND_NODES
    11. Perform final verification

    Troubleshooting Lessons

    1. Don’t trust the top-level TXK error blindly

    This:

    Invalid APPS database user credentials

    does not necessarily mean the APPS password is wrong.

    Always inspect:

    validate_apps_password.log

    In this case it exposed:

    ORA-28000: The account is locked.

    2. Check for external applications causing APPS lockouts

    If APPS repeatedly becomes:

    LOCKED(TIMED)

    don’t continuously unlock it and retry.

    Look for applications such as:

    • SplashBI
    • integrations
    • monitoring tools
    • application servers
    • scheduled jobs

    that may still have stale APPS credentials.

    3. In a CDB/PDB environment, verify the complete connection path

    Validate:

    • CDB
    • PDB
    • SERVICE_NAME
    • TNS alias
    • PORT
    • APPS account

    For example:

    tnsping TESTDB
    sqlplus apps@TESTDB

    4. Inspect the TXK source when the error is unclear

    The getJavaCmd function made the missing JRE requirement explicit in the source code. This was much more useful than simply treating the Invalid JDK TOP error as a generic Java problem.

    5. Take a backup before modifying AppsUtil

    The backup provided a simple rollback point:

    tar -czf $ORACLE_BASE/TESTDB/appsutil_pre_jre_fix_$(date +%Y%m%d_%H%M%S).tar.gz \
        TESTDB_dbctx.xml \
        txkSetCfgCDB.env \
        clone/jre

    Final Validation

    With AutoConfig completed successfully, the final validations confirmed that the database-side configuration was healthy and that the EBS node registration had been rebuilt:

    • FND_NODES query returned the EBSNODE with DB support active
    • APPS login successful
    • AutoConfig completed with no errors
    • txkCfgUtlfileDir.pl returned ERRORCODE = 0 for all modes
    • UTL_FILE_DIR directory objects successfully created

    The database-tier configuration was now ready for app-tier AutoConfig to follow, which would complete the clone or refresh procedure.

    Closing

    This issue initially looked like a simple APPS authentication problem. The actual troubleshooting required following the failure through several layers: APPS account state → PDB/service connectivity → authentication log inspection → identification of external authentication interference → TXK environment validation → prerequisite verification → directory object creation → EBS node cleanup → AutoConfig.

    The key was to validate each layer independently and avoid assuming causality between separate findings. The APPS lockout issue and the missing JRE issue were distinct problems requiring distinct solutions.

    ما شاء الله

  • When OPMN Enters a Restart Loop: Troubleshooting Oracle EBS OC4J Instability on AIX

    How I Tracked Down a Crash Sequence Across EBS Application Logs, OPMN, and AIX OS Events

    Alhamdulillah.

    Around 3 AM, the production EBS application tier was in an unstable state. The application tier was experiencing repeated process crashes and restart failures, and the OPMN logs showed multiple processes entering a recovery cycle.

    I start scrolling through logs and find the kind of chaos that makes troubleshooting interesting: OACORE processes that won’t stay alive, Forms instances crashing in sequence, OPMN repeatedly detecting failed JVM processes and attempting to restart them.

    This is the story of how a single incident revealed the importance of timeline building, log correlation, and knowing the difference between recovery and root cause.

    The Environment

    • Oracle E-Business Suite R12.1
    • AIX 7.1
    • OC4J 10.1.3 with OPMN management
    • IBM Java 7
    • Multiple OACORE and Forms processes

    The First Red Flag

    I start with the OACORE process startup logs. The timeline shows a clean start:

    20:57 — OACORE Startup
    26/08/12 20:57:06 Start process

    But three seconds later, something unexpected appears. The JVM is configured with 2560 MB heap and Gencon garbage collection. Then:

    26/08/12 20:57:09 WARNING: GC: Unable to access pending References.
    26/08/12 20:57:09 WARNING: GC: Unable to access pending Reference lock.

    That’s interesting, but not necessarily fatal. GC warnings can be transient. I keep digging.

    In the same timeframe, OACORE logs show an RMI failure:

    Error: Could not connect to the remote server
    caused by: oracle.oc4j.security.KeyExchange.getSecretKey
    caused by: Unsupported secret key algorithm: DES

    This is worth noting. An unsupported DES algorithm error in the OC4J RMI layer. But here’s the thing: I have two observations now, and I don’t yet know if they’re related, or if either one caused what happens next.

    The Cascade

    Fast forward to 01:26 AM on August 13. The OPMN logs suddenly light up:

    01:26 — Multiple Forms Processes Crash
    26/08/13 01:26:07 Process Crashed: default_group~forms~default_group~2
    26/08/13 01:26:07 Process Crashed: default_group~forms~default_group~5
    26/08/13 01:26:07 Process Crashed: default_group~forms~default_group~7
    26/08/13 01:26:07 Process Crashed: default_group~forms~default_group~8
    26/08/13 01:26:07 Process Crashed: default_group~forms-c4ws~default_group~1

    Not just one. Not even two. Five processes are crashing in the same second. The simultaneous failure of multiple Forms-related processes suggested that the issue was broader than a single application process failure.

    OPMN immediately begins detecting these failures. It does what it’s designed to do: attempt to restart failed processes. But the restart attempts are not succeeding cleanly:

    Process Start Error: default_group~forms~default_group~4
    Failed to construct stop command
    Forcefully Terminating Process
    Could not connect to socket while pinging an OC4J process
    Operation: internal (Connection refused)

    OPMN detects the failed processes and repeatedly attempts to restart them, but several restart attempts encounter process communication, socket, and port-information errors. This is the kind of situation where the logs quickly become a wall of repeated error messages as OPMN continues attempting to recover the affected processes.

    The Port Information Mystery

    As I dig deeper into the OPMN logs, I find another clue that doesn’t quite fit the picture yet:

    Host and Port information for port type jms not sent by the OC4J process
    WARNING: OC4J did not send the protocol value for port id: jms

    OPMN relies on port information to manage processes. OPMN was not receiving the expected JMS port/protocol information from the OC4J process, which complicated process management and restart attempts.

    At this point I have:

    • GC warnings on OACORE startup
    • An RMI/DES algorithm error
    • Multiple OC4J processes crashing simultaneously
    • OPMN unable to restart them cleanly
    • Missing JMS port/protocol information

    But which one caused the others? That’s when I make an important decision: instead of trying to decide, I document what I observe and build a timeline.

    Build a Timeline, Not a Theory

    When several application processes fail around the same period, it is tempting to take the first recognizable error and declare it the root cause. In this incident, the OACORE GC warnings and OC4J DES error were early clues, but the subsequent OPMN logs showed that the failure was broader.

    At this point, I have a comprehensive picture of application failures. But I’ve been told the server was rebooted. So I check the AIX logs.

    Incident Timeline

    Time Observation
    Aug 12, 20:57 OACORE processes started
    20:57:09 IBM JVM GC warnings observed (Unable to access pending References)
    20:57 OC4J RMI connection failure — Unsupported secret key algorithm: DES
    Aug 13, 01:26:07 Multiple Forms / Forms-C4WS processes crashed simultaneously
    01:28 onward OPMN restart attempts encountered process start, socket, and port-information errors
    02:36 AIX system shutdown recorded; system subsequently rebooted
    After reboot Application services recovered and remained stable

    The OS Logs Tell a Different Story

    Now I verify the OS timeline. First, boot information:

    who -b

    This tells me the boot time was Aug 13 at 02:36. Next I check the AIX error log with a time-window query around the known failure period:

    errpt -s 0813010026 -e 0813030026

    This returns:

    2BFA76F6   0813023626 T S SYSPROC
    SYSTEM SHUTDOWN BY USER

    Confirmed: SYSTEM SHUTDOWN BY USER at 02:36.

    02:36 — AIX Reboot
    System boot time: Aug 13 02:36

    After the reboot, the application services came back up and remained stable.

    What the Logs Proved — and What They Didn’t

    Proved by the evidence:

    • Multiple EBS application processes crashed
    • OPMN attempted recovery and restarts
    • Several restart attempts encountered communication and port-related errors
    • AIX recorded a system shutdown by user at 02:36
    • who -b confirmed the system boot time as 02:36
    • Application services recovered after the reboot

    Not proved by the evidence:

    • That the GC warnings caused the incident
    • That the DES error caused the process crashes
    • That the JMS port issue was the initiating failure
    • That the reboot fixed the underlying root cause
    • The exact initiating cause of the overall process-crash cascade

    The Critical Distinction

    Here’s where I have to be careful about my conclusions.

    The reboot restored service. That’s a fact. But did the reboot fix the root cause, or did it just clear transient state? These are two different things.

    A reboot can:

    • Clear unstable JVM runtime state
    • Terminate stuck processes
    • Clear transient socket/process communication state
    • Reinitialize application-tier processes and their associated listeners/ports

    None of those tell me what originally triggered the failure.

    What I can confirm:

    • OACORE: Startup with GC warnings
    • OC4J RMI: DES algorithm error
    • Forms and Forms-C4WS: Multiple process crashes during the recovery/restart sequence
    • OPMN: Multiple restart attempts encountered process communication failures, connection refusals, and missing JMS port/protocol information
    • Recovery: Reboot restored stability

    What I cannot conclusively determine from logs: the exact initiating cause of the cascade.

    When to Raise an Oracle Support SR

    In production, your first priority is recovery. But recovery should not be your last action.

    If you encounter OC4J/OPMN instability involving multiple process crashes and restart failures, here’s the right approach:

    Before you reboot:
    • If service impact is acceptable, preserve application logs, OPMN logs, and OS error logs (errpt)
    • Consider opening an SR with Oracle Support before recovery actions
    • Provide an SR reference for all follow-up communication

    If service impact demands immediate recovery:
    • Proceed with the reboot
    • Collect and preserve log artifacts afterward
    • Raise the SR as soon as practical with the preserved log artifacts
    • Include full OPMN, OACORE, Forms logs and AIX errpt output

    An SR with Oracle Support positions your incident for definitive analysis. It moves you from “we rebooted and it worked” to “here’s what happened, and here’s what Oracle Support says about it.”

    The Troubleshooting Checklist

    When you see OC4J instability, use these commands to build your timeline:

    Grep for key patterns across logs:

    grep -n -E "GC: Unable|Unsupported secret|Process Start Error|Process Crashed|Connection refused|Exception|ERROR|FATAL" <oacore_log>

    Check OPMN for the restart cycle:

    grep -n -E "Process Crashed|Process Start Error|Connection refused|Port information" <opmn.log>

    Verify boot timeline and OS events:

    who -b && uptime && last reboot | head -5

    Extract the error events in a time window (the most useful approach):

    errpt -s 0813010026 -e 0813030026   # Adjust dates for your incident

    This time-window query is much more powerful than a simple grep because it shows you events in context, within the period your incident occurred.

    What I Learned

    Alhamdulillah for this incident, because it reinforced several critical principles:

    The first error is not the root cause. I started with GC warnings and an RMI error. But the real story emerged from the sequence of crashes, not from the opening symptoms.

    Build a timeline, not a theory. A timeline shows sequence and correlation; theories can introduce assumptions. Timestamps tied together the OACORE observations, the Forms crashes, OPMN’s restart failures, and ultimately the reboot recovery.

    Recovery and RCA are different questions. The reboot answered “what restored service?” but not “what caused the failure?” It’s important to say the difference out loud.

    Correlate application and OS logs. OPMN logs showed application behavior; AIX errpt showed OS timeline. Together they tell the full story.

    Open an SR when multiple OC4J components fail. When you have a cascade of crashes involving Forms, OACORE, and OPMN restart failures, that’s beyond the scope of “try restarting the services.” Engage Oracle Support early with an SR. It positions you for definitive analysis and creates a record for future reference.

    Closing Thoughts

    This incident reinforced something I’ve learned through years of production troubleshooting in EBS and Oracle Database: patience with logs pays off.

    The reboot restored application stability, but the available evidence did not establish whether the reboot cleared a transient runtime condition or whether the underlying initiating problem had already resolved.

    Instead of manufacturing an RCA that the logs don’t support, I documented: application symptoms → OPMN behavior → OS timeline → reboot → recovery → RCA limitation.

    For any DBA handling production incidents, this is the framework:

    1. Document what the evidence proves
    2. Clearly identify what it does not prove
    3. Continue the investigation with Oracle Support if RCA is incomplete

    ما شاء الله

  • Oracle EBS R12.2 Clone Redirects to PROD After Login: Diagnosing Stale Configuration References

    When you finish cloning an Oracle E-Business Suite R12.2 environment, the moment of truth is the login page. You hit the clone’s web entry URL, the page loads, you type your credentials… and the browser quietly throws you onto the production URL. On a multi-node app tier this is more than an annoyance — it means your freshly cloned, supposedly isolated environment is reaching back into PROD, and a careless tester could authenticate against the wrong system entirely.

    I ran into exactly this on a recent R12.2.11 clone built on Oracle Cloud Infrastructure: a three-node application tier sharing a single run/patch file system over an FSS (File Storage Service) NFS mount. The clone came up, services started, but every login attempt redirected to the PROD web entry host. The initial investigation uncovered two primary issues — phantom WebLogic managed servers carried over from the source domain, and a missing DNS A-record for the clone’s web entry hostname. Along the way I also identified several other clone-related configuration areas that can produce the same symptom, including stale profile options, OHS configuration remnants, load balancer redirects, and custom code references.

    This post walks through how the symptom presents, how to diagnose it cleanly, and the supported way to fix each cause.

    Throughout, I use placeholder names — clone-apps.example.com for the clone web entry host, prod-apps.example.com for production, and appnode1/2/3 for the three app-tier nodes. Substitute your own values.


    The architecture (why a shared file system matters here)

    The clone app tier looked like this:

    • Three application-tier nodes (appnode1, appnode2, appnode3).
    • A shared dual file system (fs1 run / fs2 patch) hosted on an OCI FSS NFS export, mounted identically on all three nodes.
    • A single WebLogic domain (EBS_domain_<SID>) living on that shared file system.

    The shared file system is the detail that makes the “phantom managed server” problem sticky. Because config.xml and the managed-server definitions physically live on the shared FSS mount, any leftover managed-server entries from the source domain are visible to every node at once. AutoConfig regenerates context-driven artifacts, but it does not, on its own, delete managed servers that no longer belong to the topology.


    The symptom

    After adcfgclone completed and the application services started:

    • The clone login page (https://clone-apps.example.com:<port>/OA_HTML/AppsLogin) rendered correctly.
    • On submitting credentials — or sometimes immediately on the redirect to the home page — the browser landed on https://prod-apps.example.com/....
    • The WebLogic Admin Console showed more managed servers than the three-node clone should have, several of them in an unreachable / shutdown state.

    Two independent problems reinforced each other: stale host references remained inside the cloned WebLogic topology, while the clone web entry hostname could not be resolved correctly. Either issue can cause redirect anomalies, but together they consistently redirected users back to PROD.


    First, rule out the context file

    Before investigating WebLogic, verify the clone context file itself doesn’t still contain production hostnames. AutoConfig can only generate correct configuration if the context values are correct, so everything downstream is built from here:

    grep -i "prod-apps.example.com" $CONTEXT_FILE
    grep -i "prod" $CONTEXT_FILE

    If PROD survives in the context, fix it there and re-run AutoConfig before chasing anything downstream — otherwise you’ll be debugging generated artifacts while the source of the bad values sits upstream.


    Root cause 1 — Phantom WebLogic managed servers

    A correctly provisioned three-node oacore service should have oacore_server1, oacore_server2, oacore_server3 (and the matching oafm, forms, forms-c4ws servers per node). The cloned domain carried extra managed servers that mapped to the source environment’s nodes — servers that pointed at listen addresses and host references belonging to PROD.

    These phantom servers do three harmful things:

    1. They keep PROD host references alive inside config.xml.
    2. They confuse the EBS service control and the Admin Server’s view of the cluster.
    3. They can answer (or fail to answer) requests in ways that surface PROD URLs.

    Diagnosing it

    Inventory what the domain actually contains versus what the topology should be:

    # What managed servers does the domain config believe in?
    grep -E "<name>|<listen-address>" \
    $EBS_DOMAIN_HOME/config/config.xml | grep -iE "oacore|oafm|forms|server"
    # What does EBS think the nodes are?
    sqlplus apps/<pwd> <<'EOF'
    COL node_name FORMAT a20
    COL server_address FORMAT a18
    COL support_cp FORMAT a10
    COL support_web FORMAT a10
    COL support_admin FORMAT a13
    SELECT node_name,
    NVL(server_address,'-') AS server_address,
    NVL(support_cp,'-') AS support_cp,
    NVL(support_web,'-') AS support_web,
    NVL(support_admin,'-') AS support_admin
    FROM fnd_nodes
    ORDER BY node_name;
    EOF

    Any managed server or fnd_nodes row that references a host which is not one of appnode1/2/3 is a phantom artifact from the source.

    It’s also worth checking the role assignments — sometimes the hostname is correct but node registrations are duplicated or carry the wrong roles:

    COL node_name FORMAT a30
    COL support_db FORMAT a10
    SELECT node_name,
    support_db,
    support_cp,
    support_web,
    support_admin
    FROM fnd_nodes
    ORDER BY node_name;

    Fixing it (the supported way)

    Do not hand-edit config.xml. EBS R12.2 ships a provisioning utility to add and delete managed servers cleanly, keeping the domain, AutoConfig, and the database registration in sync. Stop the affected services first, then delete each phantom server:

    # Stop the managed servers / services before topology changes
    $ADMIN_SCRIPTS_HOME/adstpall.sh apps/<apps_pwd>
    # Delete a phantom managed server (repeat per orphaned server / service type)
    perl $AD_TOP/patch/115/bin/adProvisionEBS.pl \
    ebs-delete-managedserver \
    -contextfile=$CONTEXT_FILE \
    -managedsrvname=oacore_server4 \
    -servicetype=oacore \
    -promptmsg=hide

    After removing every phantom server, run AutoConfig on each app node so the context, the domain, and fnd_nodes agree:

    $ADMIN_SCRIPTS_HOME/adautocfg.sh

    Then confirm fnd_nodes only lists the three real clone nodes, and the Admin Console only shows the expected per-node managed servers. If you find stale node rows after the clean-up, the standard FND_CONC_CLONE.SETUP_CLEAN → AutoConfig sequence on each tier is the canonical way to rebuild the node registration. Run it as APPS, then re-run AutoConfig on every tier:

    EXEC FND_CONC_CLONE.SETUP_CLEAN;
    COMMIT;

    (Always take that step with the DBA team’s sign-off on a shared environment.)


    Root cause 2 — The missing DNS A-record

    With the phantom servers gone, the redirect still misbehaved intermittently. The reason was simpler and entirely outside EBS: the clone’s web entry hostname had no DNS A-record.

    The login flow builds its target URL from the AutoConfig web entry variables. Check them:

    grep -E "s_webentryhost|s_webentrydomain|s_webentryurlprotocol|s_active_webport|s_url_protocol|s_login_page" \
    $CONTEXT_FILE

    It’s worth proving the generated login URL, not just the host variable — if AutoConfig hasn’t fully taken, these still show a PROD host and you’ll be chasing DNS for a problem that lives in the context:

    grep -i "webentry" $CONTEXT_FILE
    grep -i "login_page" $CONTEXT_FILE

    The context correctly named clone-apps.example.com as s_webentryhost. But on the app nodes — and for clients — that name did not resolve:

    nslookup clone-apps.example.com
    # ** server can't find clone-apps.example.com: NXDOMAIN
    dig +short clone-apps.example.com
    # (empty)

    Because the clone web entry host was not resolvable, requests that relied on generated URLs could not consistently resolve back to the clone environment. At the same time, stale PROD references still lived inside the cloned WebLogic topology. Together these two conditions caused redirects to be generated using PROD host information, sending users away from the clone — which is why fixing the phantom servers alone wasn’t enough. To be clear, EBS does not contain any built-in mechanism that redirects a clone to production. Such redirects are almost always caused by stale configuration, profile options, WebLogic topology artifacts, load balancer settings, or DNS resolution — not by EBS doing anything magical. The browser is simply following a redirect built from stale host values. Name resolution has to work and the topology has to be clean.

    Fixing it

    Add an A-record for the clone web entry host in the appropriate DNS zone, pointing at the clone’s web-tier listen address (or its load balancer / OCI public-or-private IP, depending on your access path):

    clone-apps.example.com. IN A 10.x.x.x

    If a DNS change isn’t immediately possible and you only need the app nodes to resolve it for validation, a temporary /etc/hosts entry on each of appnode1/2/3 will confirm the theory — but a proper A-record is the real fix, because clients need to resolve it too:

    10.x.x.x clone-apps.example.com clone-apps

    Verify resolution from each node and re-test:

    for n in appnode1 appnode2 appnode3; do
    echo "== $n =="; ssh $n "nslookup clone-apps.example.com | tail -3"
    done

    Before concluding the issue persists, test using an incognito/private browser session or clear the browser cache. Browsers frequently cache redirects, cookies, and DNS information that can make a corrected environment appear unchanged.


    Root cause 3 — Stale profile option URLs (the other usual suspect)

    Even when DNS resolves and the WebLogic topology is clean, a clone can still throw users at PROD because profile option values were copied straight from the source. These are among the most common causes of a redirect-to-PROD, and they deserve a deliberate check rather than a passing glance. The usual culprits are APPS_WEB_AGENT, APPS_FRAMEWORK_AGENT, APPS_SERVLET_AGENT, and ICX_FORMS_LAUNCHER.

    Target them directly:

    COL profile_option_name FORMAT a30
    COL profile_option_value FORMAT a80
    SELECT fpo.profile_option_name,
    fpov.profile_option_value
    FROM fnd_profile_option_values fpov,
    fnd_profile_options_vl fpo
    WHERE fpov.profile_option_id = fpo.profile_option_id
    AND fpo.profile_option_name IN
    ('APPS_WEB_AGENT',
    'APPS_FRAMEWORK_AGENT',
    'APPS_SERVLET_AGENT',
    'ICX_FORMS_LAUNCHER');

    Or sweep more broadly for any value still carrying a PROD host:

    COL profile_option_name FORMAT a30
    COL profile_option_value FORMAT a80
    SELECT fpo.profile_option_name,
    fpov.profile_option_value
    FROM fnd_profile_option_values fpov,
    fnd_profile_options_vl fpo
    WHERE fpov.profile_option_id = fpo.profile_option_id
    AND UPPER(fpov.profile_option_value) LIKE '%PROD%';

    Most of these are AutoConfig-managed, so the right fix is almost always to correct the context and re-run AutoConfig rather than to update the profile value by hand. Hand-updating a profile that AutoConfig owns just means it reverts on the next run. If AutoConfig keeps recreating the wrong value, fix the context file or web entry settings first; otherwise the next AutoConfig run simply reintroduces the problem.


    Other places a PROD reference hides: OHS and the OCI load balancer

    A surprising share of clone redirects originate outside the database and the WebLogic domain entirely — in the web tier configuration that AutoConfig generates, or in the load balancer sitting in front of it. Worth checking these early rather than last.

    Oracle HTTP Server (OHS). Generated OHS config — mod_wl_ohs.conf chief among them — can carry PROD host references. Rather than hard-coding version-specific paths, grep the web-tier and FMW homes broadly:

    grep -R "prod-apps.example.com" \
    $INST_TOP \
    $EBS_DOMAIN_HOME/config \
    $FMW_HOME \
    $ORACLE_HOME 2>/dev/null

    OCI load balancer / reverse proxy. If an OCI Load Balancer (or any reverse proxy) fronts the environment, the redirect can be introduced at that layer even after EBS is fully corrected. Verify:

    • Host header preservation — the backend should receive the clone host, not a rewritten PROD one.
    • Backend set configuration — backends point at the clone app nodes, not PROD.
    • SSL/TLS termination — the protocol and host the LB forwards match what AutoConfig expects (s_webentryurlprotocol, s_active_webport).
    • Redirect rules / rule sets — no listener rule is rewriting the host to PROD.

    I’ve seen an OCI LB listener keep sending users to PROD long after the EBS tier itself was spotless, purely because of a stale redirect rule on the listener.

    Custom code and JARs. Customizations are a notorious hiding place — hardcoded URLs in custom packages, JSPs, or Java survive every clone untouched by AutoConfig. Grep the custom homes too:

    grep -R "prod-apps.example.com" \
    $XX_TOP \
    $JAVA_TOP \
    $CUSTOM_TOP 2>/dev/null

    Validation checklist after remediation

    1. nslookup / dig resolves clone-apps.example.com from all three app nodes and from a client workstation.

    2. WebLogic Admin Console lists only the expected per-node managed servers, all in RUNNING state.

    3. fnd_nodes contains only appnode1/2/3 (check support_cp, support_web, support_admin); no PROD host references remain.

    4. No stale source context files are still registered. Old registrations sometimes survive a clone and cause confusion later during AutoConfig or service management:

    COL node_name FORMAT a20
    COL ctx_file FORMAT a60
    SELECT node_name,
    ctx_type,
    NVL(path,'-') AS ctx_file,
    status
    FROM fnd_oam_context_files
    WHERE status = 'S'
    ORDER BY node_name;

    In a clean clone, every active context file should belong to the clone environment. Any remaining source-environment context registration should be reviewed and removed before further AutoConfig runs.

    5. The profile options from Root cause 3 (APPS_WEB_AGENT, APPS_FRAMEWORK_AGENT, APPS_SERVLET_AGENT, ICX_FORMS_LAUNCHER) all carry clone values, not PROD — re-run the targeted query from that section to confirm.

    6. The login page loads from the clone URL and — critically — the post-login redirect stays on clone-apps.example.com, never bouncing to prod-apps.example.com.

    7. Sweep the entire configuration for the PROD hostname, not just the context file. PROD remnants love to hide in OHS configs, mod_wl_ohs.conf, generated XML, and custom integrations:

    grep -R "prod-apps.example.com" \
    $INST_TOP \
    $EBS_DOMAIN_HOME/config \
    $FMW_HOME 2>/dev/null

    Anything this turns up needs to be corrected (and usually re-generated via AutoConfig) before users find it for you.

    8. No context file registered in the database still points at a PROD path. Stale PROD context registrations can cause odd behaviour long after the clone:

    COL node_name FORMAT a20
    COL path FORMAT a70
    SELECT node_name,
    path
    FROM fnd_oam_context_files
    WHERE UPPER(path) LIKE '%PROD%';

    9. If an OCI Load Balancer or reverse proxy fronts the environment, verify its listener rules, backend sets, host-header forwarding, and SSL termination settings contain no PROD references.


    Lessons learned / a small post-clone checklist

    Cloning R12.2 onto a shared file system multi-node tier adds two checks that single-node clones let you skip:

    • Audit the managed-server topology immediately after adcfgclone. On a shared file system the source’s managed servers ride along inside config.xml. Delete phantoms with adProvisionEBS.pl ebs-delete-managedserver, never by editing XML, and re-run AutoConfig.
    • Resolve the web entry hostname before you trust the login page. A clone that “logs you into PROD” is very often a DNS problem wearing an EBS costume. Create the A-record as part of the clone runbook, not as a reaction to the redirect.
    • Treat a redirect-to-PROD as a stop-the-line event. Until both topology and name resolution are clean, assume the clone can still touch production and keep testers out.
    • Run FND_CONC_CLONE.SETUP_CLEAN before AutoConfig in cloned environments. This rebuilds node registrations and context metadata cleanly and helps prevent stale topology information from the source environment persisting in the clone. (On a shared environment, run it with the DBA team’s sign-off.)

    In this case, three unglamorous root causes — leftover managed servers, a missing DNS record, and stale profile option URLs — combined to produce the redirect. In practice, however, most redirect-to-PROD incidents come down to one broader problem: stale production references surviving the clone process. The fastest path to resolution is a systematic sweep of WebLogic, DNS, profile options, context files, OHS configuration, load balancers, and custom code until every production reference is gone.


    Have you hit a different flavour of the clone redirect? The web entry variables, SSL/load-balancer termination, and s_login_page overrides each have their own way of sending you to the wrong host — happy to compare notes in the comments.

  • ORA-00257: Archiver Error in Oracle 19c CDB — Diagnosis and Resolution

    Background

    This post documents a real production incident where an Oracle E-Business Suite (EBS) environment became completely unresponsive due to a full Fast Recovery Area (FRA). Users were reporting that everything was either slow or hanging — a classic sign that something fundamental had broken at the database layer.

    Symptoms

    • EBS application users reporting sessions hanging or extremely slow response
    • sqlplus apps/<password> failing with:
    ORA-00257: Archiver error. Connect AS SYSDBA only until resolved.
    • Non-SYSDBA connections completely blocked
    • 30 FNDLIBR (Concurrent Manager) processes running on the application server — higher than expected for a QA environment

    Environment

    • Oracle Database 19c (CDB/PDB architecture)
    • PDB: Application database PDB
    • EBS 12.2 on AIX
    • FRA configured on ASM diskgroup (+RECO), size 4095 GB
    • No explicit log_archive_dest — archivelogs defaulting to FRA

    Step 1 — Identify the Root Cause

    Connected to the CDB as SYSDBA and confirmed the error:

    SHOW PARAMETER db_recovery_file_dest;
    NAME                        TYPE        VALUE
    --------------------------- ----------- ------
    db_recovery_file_dest       string      +RECO
    db_recovery_file_dest_size  big integer 4095G

    Checked FRA usage:

    COLUMN name           FORMAT A10
    COLUMN limit_gb       FORMAT 999,999.99 HEADING 'LIMIT GB'
    COLUMN used_gb        FORMAT 999,999.99 HEADING 'USED GB'
    COLUMN reclaimable_gb FORMAT 999,999.99 HEADING 'RECLAIMABLE GB'
    COLUMN number_of_files FORMAT 99999     HEADING 'FILES'
    
    SELECT name,
           ROUND(space_limit/1024/1024/1024,2)       limit_gb,
           ROUND(space_used/1024/1024/1024,2)        used_gb,
           ROUND(space_reclaimable/1024/1024/1024,2) reclaimable_gb,
           number_of_files
    FROM   v$recovery_file_dest;

    Output:

    NAME         LIMIT GB     USED GB  RECLAIMABLE GB  FILES
    ---------- ----------- ----------- -------------- ------
    +RECO         4,095.00    4,075.65            .00   2426

    FRA was at 99.5% — 4,075 GB used out of 4,095 GB, zero reclaimable, 2,426 archivelog files.

    This was the root cause. With the FRA full and nothing reclaimable, the archiver (ARCn) process could not write new archive logs, blocking all database activity.

    Step 2 — Assess Backup Status Before Taking Action

    Before deleting any archivelogs, it is critical to understand the backup posture. Blindly deleting archivelogs without knowing the backup state can leave the database unrecoverable.

    Started an RMAN session and ran a crosscheck first:

    rman target /
    RMAN> crosscheck archivelog all;

    All 2,416 objects returned “validation succeeded” — no expired logs. This meant the FRA was genuinely full of valid, undeleted archivelogs.

    Next, checked backup history:

    RMAN> list backup summary;

    Backups were listed daily going back several weeks — however, on closer inspection:

    SELECT session_key,
           TO_CHAR(start_time,'DD-MON-YY HH24:MI') start_time,
           TO_CHAR(end_time,'DD-MON-YY HH24:MI')   end_time,
           status,
           input_bytes,
           output_bytes
    FROM   v$rman_backup_job_details
    ORDER  BY start_time DESC
    FETCH FIRST 10 ROWS ONLY;

    Output revealed a critical finding:

    SESSION_KEY  START_TIME         END_TIME           STATUS    INPUT_BYTES  OUTPUT_BYTES
    -----------  -----------------  -----------------  --------  -----------  ------------
          19986  30-APR-26 01:00    30-APR-26 01:00    COMPLETED           0         98304
          19904  29-APR-26 01:00    29-APR-26 01:00    COMPLETED           0         98304
    • INPUT_BYTES = 0 — no datafiles were being backed up
    • OUTPUT_BYTES = 98304 (96 KB) — only a controlfile/SPFILE autobackup
    • Jobs completing in under a minute — impossible for a real full DB backup

    Additionally:

    RMAN> list backup of archivelog all;
    -- specification does not match any backup in the repository

    No archivelog backups existed at all. The scheduled backup job was not performing proper datafile or archivelog backups — a separate issue to be addressed post-incident.

    Step 3 — Escalation and Approval

    Given that there were no archivelog backups and the datafile backup was questionable, the decision to delete archivelogs and  Approval was obtained with the instruction to start conservatively — delete older than 15 days first, then 7 days if needed.

    Step 4 — Resolution

    First attempt — delete older than 15 days:

    RMAN> delete noprompt archivelog until time 'SYSDATE-15';

    RMAN returned warnings:

    RMAN-08138: warning: archived log not deleted - must create more backups

    This is because the RMAN retention policy was blocking deletion of logs that had never been backed up. With Tier 3 approval, used the force option to override:

    RMAN> delete noprompt force archivelog until time 'SYSDATE-15';

    This ran successfully, deleting archivelogs from January through late April.

    FRA usage after deletion:

    USED_GB  RECLAIMABLE_GB  NUMBER_OF_FILES
    -------  --------------  ---------------
     246.71               0              149

    Over 3,800 GB freed — FRA dropped from 99.5% to ~6%.

    Step 5 — Verification

    Forced a log switch and verified archiver status:

    ALTER SYSTEM ARCHIVE LOG CURRENT;
    
    SELECT dest_id, status, error
    FROM   v$archive_dest
    WHERE  status != 'INACTIVE';

    Output:

    DEST_ID  STATUS    ERROR
    -------  --------  -----
          1  VALID

    Archiver resumed successfully. Application connectivity was restored and users confirmed sessions were working normally.

    Redo Log Status Check

    As part of the verification, also confirmed redo log health:

    SELECT thread#,
           sequence#,
           TO_CHAR(first_time,'DD-MON-YY HH24:MI:SS') first_time,
           first_change#,
           archived,
           status
    FROM   v$log
    ORDER  BY thread#, sequence#;
    THREAD#  SEQUENCE#  FIRST_TIME                FIRST_CHANGE#  ARC  STATUS
    -------  ---------  ------------------------  -------------  ---  -------
          1       2417  05-MAY-26 01:56:44         1.7867E+10    NO   INACTIVE
          1       2418  05-MAY-26 03:27:20         1.7867E+10    NO   INACTIVE
          1       2419  05-MAY-26 07:57:10         1.7868E+10    NO   CURRENT

    No stuck or unarchived redo logs — database in healthy state.

    Incident Summary

    Item Detail
    Error ORA-00257: Archiver error
    Root Cause FRA (+RECO ASM diskgroup) at 99.5% capacity
    FRA Before 4,075 GB used / 2,426 files
    FRA After 246 GB used / 149 files
    Action Taken delete noprompt force archivelog until time 'SYSDATE-15'
    Space Freed ~3,829 GB
    Resolution Time ~45 minutes from identification to restoration

    Key Lessons Learned

    1. Monitor FRA Proactively

    Set up OEM 13c threshold alerts on FRA usage at 70% and 85%. Do not wait for ORA-00257 to discover the problem.

    SELECT ROUND(space_used/space_limit*100,2) pct_used
    FROM   v$recovery_file_dest;

    Alert when this exceeds 80%.

    2. Always Check Backup Status Before Deleting Archivelogs

    In this incident, the backup job appeared to be running daily but was only backing up the controlfile (INPUT_BYTES=0). This is a serious gap — verify actual backup content, not just job status.

    3. Investigate the Backup Job

    A proper RMAN backup script for a 19c CDB should include:

    BACKUP DATABASE PLUS ARCHIVELOG DELETE INPUT;

    4. Consider an Archivelog Deletion Policy

    If archivelog backups are not being taken, configure an RMAN retention policy to prevent FRA accumulation:

    CONFIGURE RETENTION POLICY TO RECOVERY WINDOW OF 7 DAYS;

    5. FRA Sizing Review

    Even at 4095 GB, the FRA filled up due to months of uncleaned archivelogs. Review archivelog generation rate and size FRA accordingly, or implement regular cleanup.

    Conclusion

    ORA-00257 is one of those errors that brings an entire EBS environment to its knees instantly. The fix itself is straightforward — free up FRA space — but the investigation matters. Rushing to delete archivelogs without understanding the backup posture can result in an unrecoverable database.

    In this case, careful investigation revealed a deeper issue with the backup job that would have gone unnoticed had we not looked. Always verify, always escalate, and always get approval before deleting recovery-critical files.


    Syed Anwar Ahmed is an Oracle Apps DBA with over 11 years of production experience across Oracle EBS, Database, RAC, GoldenGate, and OEM environments. He writes about real-world Oracle incidents at syedanwarahmedoracle.blog.

  • P1 Incident: /dbbackup Filesystem 100% Full — How We Traced, Fixed, and Recovered Two Failed RMAN Backups in One Night

    🔴 Incident Overview

    Severity P1 — Two production database backups failed
    Environment Oracle 19c (19.30) on Linux x86-64
    Backup Tool RMAN with Recovery Catalog
    Backup Volume /dbbackup — 1TB LVM filesystem
    Databases Affected DBPRO01 (12:30 failure), DBPRO02 (22:30 failure)
    Total Space Recovered ~492G (disk went from 100% → 52%)

    1. The Alerts — Two Failures, Same Root Cause

    It started with an RMAN failure at 22:30. The backup script for DBPRO02 fired on schedule and died within 2 minutes. The RMAN log told the story clearly:

    RMAN-03009: failure of backup command on c4 channel at 22:32:13
    ORA-19502: write error on file "/dbbackup/DBPRC02/rman/DiffInc_DBPRC02_4u4mi8bf"
    ORA-27072: File I/O error
    Additional information: 4
    

    Three more channels followed — c1, c2, c3 — all crashing at exactly 22:32:48. When multiple channels fail simultaneously at the same timestamp, it almost always means one thing: the destination filesystem just hit 100%.

    A quick check confirmed it:

    $ df -hP /dbbackup
    Filesystem                        Size  Used Avail Use%
    /dev/mapper/orabkupvg-orabkuplv1 1023G 1020G  3.3G 100%
    

    1TB volume. 3.3G free. Completely full.

    What we did not know yet — digging into backup history would reveal that DBPRO01 had already failed at 12:30 that same day for the same reason, 10 hours earlier. Two databases unprotected on the same night.


    2. The Investigation — Folder by Folder

    The first step was understanding what was consuming the disk. One command gave us the top-level picture:

    $ du -sh /dbbackup/*
    744G    DBPRC01
    152G    ColdBackup_11April2026
     41G    DBPRC02
     26G    DBPRC03
     15G    DBPRO01
    7.7G    JAN2026_CPU
    7.7G    OCT2025_CPU
    5.3G    infra_arch
    

    744G inside DBPRC01 alone — 73% of the entire disk. That was our primary suspect.

    Drilling into DBPRC01

    $ du -sh /dbbackup/DBPRC01/rman/* | sort -rh | head -10
    7.5G    DiffInc_DBPRC01_fl4lumij
    7.5G    DiffInc_DBPRC01_eg4lrnh5
    7.5G    DiffInc_DBPRC01_b44lc7uh
    ...
    

    Every single file was a DiffInc_ or ArchivelogAll_ backup piece. No variety. No cleanup. Just backup after backup piling up.

    $ ls /dbbackup/DBPRC01/rman/ | wc -l
    1522
    

    1,522 backup pieces. We checked the oldest and newest:

    Oldest file on disk:  2022-05-07
    Newest file on disk:  2026-04-25
    

    Four years of backup files on disk — or so we thought.


    3. The RMAN Investigation — Where Things Got Interesting

    We connected RMAN to the database and ran the retention check:

    RMAN> SHOW RETENTION POLICY;
    CONFIGURE RETENTION POLICY TO REDUNDANCY 30;
    

    REDUNDANCY 30. This tells RMAN to keep the last 30 complete backup copies of every datafile before considering anything obsolete.

    Next logical step — check what RMAN considers obsolete:

    RMAN> REPORT OBSOLETE;
    no obsolete backups found
    

    Nothing? With 1,522 files on disk?

    We ran CROSSCHECK BACKUP — all 1,693 objects came back AVAILABLE. Then we checked the actual date range RMAN was tracking from the database control file:

    SELECT TO_CHAR(MIN(completion_time),'DD-MON-YYYY') oldest,
           TO_CHAR(MAX(completion_time),'DD-MON-YYYY') newest,
           COUNT(*) total_pieces
    FROM v$backup_piece_details
    WHERE status = 'A';
    
    OLDEST          NEWEST          TOTAL_PIECES
    03-DEC-2025     25-APR-2026     1541
    

    The control file only tracks pieces from December 2025 onwards — about 5 months. The 2022/2023 files seen on disk were old directories and scripts, not backup pieces. All 1,541 current pieces were legitimate and RMAN considered every one of them necessary under REDUNDANCY 30.

    This was the key insight: RMAN was not broken. The retention policy itself was the problem.


    4. Root Cause — The Architecture Trap

    The deeper investigation revealed something unexpected. Looking at the actual RMAN backup script:

    connect target rman/password@DBPRO01
    ...
    format '/dbbackup/DBPRC01/rman/DiffInc_%d_%u'
    (database);
    ...
    delete obsolete;
    

    DBPRO01 (the production database) was backing up INTO the DBPRC01 directory. The directory names suggested one database but contained another database’s backups entirely. The naming convention was PRO to PRC — production database backups stored in the production-copy directory.

    This pattern existed for all three database pairs on the server. Each production database backed up into its corresponding copy directory.

    The delete obsolete command was in the script — but with REDUNDANCY 30 and weekly Level 0 backups, obsolete only kicks in after 30 complete Level 0 cycles. That is 30 weeks = 7.5 months of retention. Since the current tracking window was only 5 months, delete obsolete ran every night and found absolutely nothing to delete.

    The math:

    Retention policy REDUNDANCY 30
    Level 0 frequency Weekly (Sundays)
    Effective retention period ~30 weeks / 7.5 months
    Backup tracking since December 2025 (~5 months)
    Result delete obsolete finds nothing — ever
    Daily backup size ~7–7.5G per run
    Total accumulated 744G

    Adding fuel to the fire — the patching activity on April 18 triggered an extra Level 0 backup, followed by the regular Sunday Level 0 on April 19. Two large Level 0 runs (~27G each) within 24 hours wrote the final ~54G that pushed the disk over the edge.


    5. Secondary Findings During Investigation

    OCT2025 CPU Patch Artifacts (7.7G)

    The October 2025 CPU patch files (zip archives + extracted directories) were still sitting in /dbbackup/OCT2025_CPU/. A quick OPatch check confirmed the database had since been patched to 19.30 (January 2026 RU) — the October 2025 patches were fully superseded and rolled back from inventory. Safe to delete immediately.

    $ $ORACLE_HOME/OPatch/opatch lsinventory | grep -E "38291812|38194382"
    # Empty — neither Oct 2025 patch in inventory anymore
    

    5-Year-Old Pre-Migration Export Dumps

    Three directories contained Oracle 11.2.0.4 export dumps from January–March 2021 — taken before the migration to 19c. With the database now running 19.30, these had zero recovery value but occupied ~14G collectively. Flagged for manager approval before deletion.

    Recovery Catalog Version Mismatch

    The original RMAN log flagged this warning:

    PL/SQL package RMAN.DBMS_RCVCAT version 19.11.00.00 in RCVCAT database is not current
    PL/SQL package RMAN.DBMS_RCVMAN version 19.11.00.00 in RCVCAT database is not current
    

    The recovery catalog is running 19.11 packages while the RMAN client is now 19.30. Non-critical tonight but requires UPGRADE CATALOG in the next maintenance window.


    6. The Fix — Emergency Space Recovery

    With management approval obtained, we executed a time-based delete — keeping the last 30 days of backups and removing everything older:

    RMAN> DELETE NOPROMPT BACKUP COMPLETED BEFORE 'SYSDATE-30';
    

    This command does three things atomically:

    1. Queries catalog/controlfile for all pieces completed before the cutoff date
    2. Deletes the physical files from disk
    3. Removes the records from RMAN catalog — no orphaned entries, no catalog drift

    The output scrolled for several minutes:

    deleted backup piece
    backup piece handle=/dbbackup/DBPRC01/rman/DiffInc1_DBPRC01_6u4jaaih ...
    deleted backup piece
    backup piece handle=/dbbackup/DBPRC01/rman/ArchivelogAll_DBPRC01_784jab6o ...
    ...
    Deleted 1072 objects
    

    1,072 backup pieces deleted. Catalog updated. Disk checked:

    BEFORE:  Used 1020G  Avail 3.3G  (100%)
    AFTER:   Used  536G  Avail 488G   (53%)
    

    Then the OCT2025_CPU directory was removed:

    $ rm -rf /dbbackup/OCT2025_CPU/
    $ df -hP /dbbackup
    Used 528G  Avail 495G  (52%)
    

    Final result: 495G free. Disk at 52%.

    Both failed backups were re-submitted immediately and ran successfully in parallel:

    $ nohup sh /opt/oracle/scripts/rman/rman_backup_DBPRO01.sh &
    $ nohup sh /opt/oracle/scripts/rman/rman_backup_DBPRO02.sh &
    
    $ jobs -l
    [1] Running   nohup sh ...rman_backup_DBPRO01.sh &
    [2] Running   nohup sh ...rman_backup_DBPRO02.sh &
    

    7. Incident Timeline

    12:30 DBPRO01 Level 0 backup fails — ORA-19502/ORA-27072 (disk full)
    22:30 DBPRO02 Level 0 backup fails — same errors, all 4 channels
    23:08 Investigation begins — df -hP /dbbackup confirms 100% full
    23:15 DBPRC01 directory identified as 744G consumer
    23:25 RMAN connected — REDUNDANCY 30 discovered
    23:35 Architecture confirmed — PRO databases backing up into PRC directories
    23:45 Root cause confirmed — 7.5-month retention, delete obsolete finds nothing
    23:50 DELETE BACKUP COMPLETED BEFORE SYSDATE-30 executed
    23:51 1,072 pieces deleted — disk drops to 53%
    23:55 OCT2025_CPU removed — disk at 52%, 495G free
    00:00 Both backup jobs re-submitted and running successfully

    8. Permanent Fix Recommendations

    Fix 1 — Change Retention Policy to RECOVERY WINDOW

    RMAN> CONFIGURE RETENTION POLICY TO RECOVERY WINDOW OF 14 DAYS;
    

    REDUNDANCY 30 with weekly Level 0s means 7.5 months of retention — far beyond what any production SLA requires. A 14-day recovery window keeps 2 weeks of backups regardless of backup frequency, and delete obsolete will actually find and remove old pieces going forward.

    Fix 2 — Add Pre-Backup Space Check to Cron Script

    #!/bin/bash
    BACKUP_FS="/dbbackup"
    THRESHOLD=20
    
    AVAIL_PCT=$(df -hP $BACKUP_FS | awk 'NR==2 {gsub(/%/,""); print 100-$5}')
    
    if [ "$AVAIL_PCT" -lt "$THRESHOLD" ]; then
      echo "ABORT: $BACKUP_FS is ${AVAIL_PCT}% free — below ${THRESHOLD}% threshold" \
        | mailx -s "BACKUP ABORTED: Low space on $BACKUP_FS" $MAILTO
      exit 1
    fi
    

    A failing backup that writes 3G before dying is worse than a backup that never starts — it wastes the last 3G of free space and leaves partial pieces on disk.

    Fix 3 — Upgrade the Recovery Catalog

    RMAN> CONNECT TARGET /
    RMAN> CONNECT CATALOG rman/password@rmancat
    RMAN> UPGRADE CATALOG;
    RMAN> UPGRADE CATALOG;   -- run twice as prompted
    

    The catalog is 2 major patch levels behind the RMAN client. Some catalog-dependent operations will start failing if left unaddressed.

    Fix 4 — Filesystem Monitoring Alert

    The FRA check scripts already email on FRA usage above 80%. The same pattern should exist for /dbbackup. A simple cron entry checking disk usage every hour with alert at 80% would have caught this days before the disk hit 100%.


    9. Key Takeaways for Oracle DBAs

    REDUNDANCY N is not always safer than RECOVERY WINDOW. REDUNDANCY 30 with weekly Level 0 backups means 7.5 months of retention — likely far beyond your RPO requirement and a silent space accumulator.

    • Always verify what delete obsolete actually deletes. If it finds nothing to delete every single night, that is a warning sign — not reassurance.
    • Check backup naming conventions carefully. When a directory named DBPRC01 contains DBPRO01 backups, retention policies applied to the wrong database RMAN configuration control the cleanup behavior.
    • Patching days generate oversized backups. A Level 0 taken manually on patch day plus the regular Sunday Level 0 the next day equals 2x the normal space consumption in 24 hours. Ensure extra headroom exists going into patch windows.
    • Use DELETE BACKUP COMPLETED BEFORE SYSDATE-N for emergency cleanup — not OS-level rm. RMAN deletes atomically update both the physical files and the catalog, preventing expired/orphaned piece confusion later.
    • Never use rm on RMAN backup pieces directly unless you follow up with CROSSCHECK BACKUP and DELETE EXPIRED BACKUP to sync the catalog.

    10. Commands Reference — Quick Cheat Sheet

    -- Check retention policy
    RMAN> SHOW RETENTION POLICY;
    
    -- Preview what would be deleted (dry run)
    RMAN> REPORT OBSOLETE;
    RMAN> LIST BACKUP COMPLETED BEFORE 'SYSDATE-30';
    
    -- Emergency cleanup — delete pieces older than 30 days
    RMAN> DELETE NOPROMPT BACKUP COMPLETED BEFORE 'SYSDATE-30';
    
    -- Standard cleanup based on retention policy
    RMAN> DELETE NOPROMPT OBSOLETE;
    
    -- Sync catalog after any OS-level file operations
    RMAN> CROSSCHECK BACKUP;
    RMAN> DELETE NOPROMPT EXPIRED BACKUP;
    
    -- Change to time-based retention (recommended)
    RMAN> CONFIGURE RETENTION POLICY TO RECOVERY WINDOW OF 14 DAYS;
    
    -- Check backup piece date range in control file
    SELECT TO_CHAR(MIN(completion_time),'DD-MON-YYYY') oldest,
           TO_CHAR(MAX(completion_time),'DD-MON-YYYY') newest,
           COUNT(*) total_pieces
    FROM v$backup_piece_details
    WHERE status = 'A';
    
    -- Check backup history
    SELECT session_key, input_type, status,
           TO_CHAR(start_time,'YYYY-MM-DD HH24:MI:SS') start_time,
           output_bytes_display, time_taken_display
    FROM v$rman_backup_job_details
    ORDER BY start_time DESC;
    

    Conclusion

    What appeared to be a simple disk full incident turned out to involve a multi-database backup architecture, a misconfigured retention policy, and a cleanup mechanism that was technically running correctly but never finding anything to clean. The fix itself — one RMAN command — took under 5 minutes. The real work was the systematic investigation to understand exactly what was safe to delete and why.

    That is Oracle DBA work in a nutshell: the fix is often simple; understanding why it is safe to run is the real job.


    If you found this useful, connect with me on LinkedIn or explore more Oracle DBA scripts on my GitHub. More incident walkthroughs at syedanwarahmedoracle.blog.

  • Stuck Archiver on Oracle 11g RAC: How a Full FRA Brought Down Archiving — and How We Fixed It Live

    Introduction

    One of the most disruptive incidents a DBA can face in a production RAC environment is a Stuck Archiver — a condition where Oracle’s archiver process (ARCn) is unable to archive online redo logs, effectively stalling all database activity. Transactions pile up, applications hang, and the business takes a hit.

    This post documents a real-world Stuck Archiver incident on a two-node Oracle 11g RAC cluster, caused by Fast Recovery Area (FRA) exhaustion. I’ll walk through the exact symptoms, diagnosis queries, root cause analysis, and the live fix — along with preventive measures to ensure this doesn’t repeat.

    Environment Overview

    Component Details
    Database Oracle 11g R2 (11.2.0.4.0)
    Architecture RAC — 2 Nodes
    Database Role PRIMARY — READ WRITE, ARCHIVELOG mode
    OS Linux (x86_64)
    FRA Location ASM Diskgroup +ARCHIVELOG
    FRA Size (pre-incident) 199 GB
    FRA Size (post-fix) 400 GB

    The Incident: What We Saw

    The alert came in the early hours of the morning. Applications were hanging, users were reporting timeouts, and both RAC instances had entered an INTERMEDIATE state. The alert log was flooded with:

    ORA-00257: archiver error. Connect internal only, until freed.
    ARC0: Error 19809 Creating archive log file to '<FRA_PATH>'
    ARCH: Archival stopped, error occurred. Will continue retrying
    ORACLE Instance PRODDB1 - Archival Error

    The archiver was stuck on both instances, and Oracle had locked down the database to internal connections only. The incident was open for approximately 45 minutes before the fix was applied and applications recovered.

    Step 1: Check Redo Log Status

    First priority — verify the state of online redo log groups. If LGWR cannot overwrite ACTIVE logs because they are unarchived, the database will hang regardless of any other fix.

    SELECT group#, status, archived, members FROM v$log ORDER BY group#;
    
    GROUP#   STATUS           ARCHIVED   MEMBERS
    ------   ---------------  ---------  -------
    1        ACTIVE           NO         2
    2        CURRENT          NO         2
    3        INACTIVE         YES        2
    4        INACTIVE         YES        2

    Groups 1 and 2 needed archiving. LGWR cannot overwrite ACTIVE or CURRENT redo logs until they are archived — this confirmed the database hang was directly caused by the stuck archiver.

    Step 2: Confirm the Archiver Status

    -- Check both RAC instances
    SELECT inst_id, instance_name, host_name, version,
           database_role, open_mode, log_mode
    FROM gv$instance ORDER BY inst_id;
    
    INST_ID  INSTANCE_N  VERSION       DATABASE_ROLE  OPEN_MODE   LOG_MODE
    -------  ----------  ------------  -------------  ----------  ----------
          1  PRODDB1     11.2.0.4.0    PRIMARY        READ WRITE  ARCHIVELOG
          2  PRODDB2     11.2.0.4.0    PRIMARY        READ WRITE  ARCHIVELOG
    
    SELECT instance_name, status, archiver FROM v$instance;
    
    INSTANCE_NAME    STATUS       ARCHIVER
    ---------------- ------------ --------
    PRODDB1          OPEN         STOPPED

    ARCHIVER = STOPPED confirmed it. Both RAC instances were in INTERMEDIATE state — the entire cluster was effectively down for application workloads.

    Step 3: Check FRA Usage

    SELECT
        space_limit / (1024*1024*1024)       AS limit_gb,
        space_used  / (1024*1024*1024)       AS used_gb,
        space_reclaimable / (1024*1024*1024) AS reclaimable_gb,
        ROUND((space_used / space_limit) * 100, 2) AS pct_used
    FROM v$recovery_file_dest;
    
    LIMIT_GB   USED_GB   RECLAIMABLE_GB   PCT_USED
    --------   -------   --------------   --------
    199        198.99     0.00            100.00

    100% FRA utilization with zero reclaimable space. The FRA on ASM diskgroup +ARCHIVELOG was completely full with 3,094 archived log files. Before proceeding, the ASM diskgroup was checked — +ARCHIVELOG had 299 GB free, confirming sufficient underlying storage for a size increase.

    Step 4: Identify What Was Consuming the FRA

    SELECT file_type,
        ROUND(space_used / (1024*1024*1024), 2)        AS used_gb,
        ROUND(space_reclaimable / (1024*1024*1024), 2) AS reclaimable_gb,
        number_of_files
    FROM v$recovery_area_usage
    ORDER BY space_used DESC;
    
    FILE_TYPE       USED_GB   RECLAIMABLE_GB   NUMBER_OF_FILES
    -----------     -------   --------------   ---------------
    ARCHIVED LOG    38.50     0.05             1,200+
    BACKUP PIECE    10.20     0.07             45
    FLASHBACK LOG    1.30     0.00             12

    Over 1,200 archived log files had piled up because the RMAN ARCH backup job had been silently failing for multiple nights.

    Step 5: Redo Volume Analysis — Identifying the Nightly Batch Spike

    SELECT TO_CHAR(first_time,'YYYY-MM-DD HH24') AS hour,
           COUNT(*) AS logs,
           ROUND(SUM(blocks*block_size)/1024/1024/1024,2) AS gb
    FROM v$archived_log
    WHERE dest_id=1
    GROUP BY TO_CHAR(first_time,'YYYY-MM-DD HH24')
    ORDER BY 1;
    Hour Archived Logs GB Generated
    Daytime (typical) 2–26 < 1.3 GB
    01:00 AM (nightly) 440–446 ~31 GB ⚠
    03:00–04:00 AM 191–411 11–28 GB ⚠
    05:00–06:00 AM 537–796 34–50 GB ⚠

    Clear Pattern — Nightly Batch Job Is the Culprit: Every night between 01:00 AM and 06:00 AM, redo generation spikes to 30–50 GB per hour. Daytime activity rarely exceeds 0.5 GB/hour. With the RMAN ARCH backup silently failing for multiple nights, these logs were never backed up or removed — they simply accumulated until the FRA hit 100%.

    The Resolution — Three Actions

    Action 1: Manually Delete Archive Logs from ASM

    Because RMAN could not run against a full FRA and there was no reclaimable space, older archived logs were manually deleted via ASMCMD:

    su - grid
    asmcmd
    
    ASMCMD> ls +ARCHIVELOG/PRODDB/ARCHIVELOG/
    ASMCMD> rm +ARCHIVELOG/PRODDB/ARCHIVELOG/2026_04_04/*
    ASMCMD> rm +ARCHIVELOG/PRODDB/ARCHIVELOG/2026_04_05/*
    # Recent logs retained to preserve recoverability

    After ASMCMD deletion, the RMAN catalog was resynced:

    RMAN> CROSSCHECK ARCHIVELOG ALL;
    RMAN> DELETE EXPIRED ARCHIVELOG ALL;

    Important: ASMCMD deletion removes files from ASM but the control file still holds references. Always follow up with CROSSCHECK and DELETE EXPIRED to leave the catalog in a consistent state.

    Action 2: Increase FRA Size Online

    -- Increase FRA from 199GB to 400GB (online, no restart required)
    ALTER SYSTEM SET db_recovery_file_dest_size = 400G SCOPE=BOTH SID='*';

    SID='*' applies the change to both RAC instances simultaneously. Immediately after, the archiver restarted automatically:

    ARC1: Archival started
    ARC2: Archival started
    ARC3: Archival started
    ORACLE Instance PRODDB1 - Archival Restarted

    Applications reconnected and transactions resumed within seconds.

    Action 3: Verify Database and Cluster Status

    SELECT instance_name, archiver FROM v$instance;
    -- PRODDB1   STARTED
    
    SELECT round(space_used/1024/1024/1024,2) used_gb,
           round(space_limit/1024/1024/1024,2) limit_gb,
           round((space_used/space_limit)*100,2) used_pct
    FROM v$recovery_file_dest;
    -- 202.80 GB / 400 GB / 50.70%
    
    SELECT group#, status, archived FROM v$log ORDER BY group#;
    -- All groups INACTIVE/YES except CURRENT group

    Full CRS cluster check via crsctl status res -t confirmed all resources ONLINE — both instances Open, TAF service live on both nodes, all ASM diskgroups healthy. Note: ora.gsd OFFLINE is expected for Oracle 11g RAC — it is a legacy component not required in this configuration.

    Root Cause Confirmed: Archive Log Backups Were Not Running

    With the database stable, investigation confirmed the RMAN ARCH backup had been silently failing for multiple nights. The cron job fired the script on schedule, but without Oracle environment variables set in the cron context (ORACLE_SID, ORACLE_HOME, PATH all unset), the script exited immediately without connecting to RMAN. The log at /tmp/RMAN_ARCH.log appeared empty — no RMAN error, nothing surfacing to the team.

    Complete Incident Chain:
    ARCH backup silently fails (missing Oracle env vars in cron) → 3,094 archived logs accumulate over multiple nights → Heavy batch redo (30–50 GB/hr, 01:00–06:00 AM) → FRA hits 100% (198.99 GB / 199 GB) → ARCn cannot write → Both instances enter INTERMEDIATE state → ORA-00257 → Applications hang → Archive logs manually deleted via ASMCMD → FRA expanded to 400 GB → Archiver restarts → Cron fix applied → ARCH backup reruns successfully → FRA space recovered → Cluster fully healthy

    Fix: Correct the Cron Environment

    Broken cron entry:

    05 * * * * /home/oracle/scripts/RMAN_Hotbackup.ksh ARCH > /tmp/RMAN_ARCH.log 2>&1

    Fixed cron entry:

    05 * * * * . /home/oracle/.bash_profile && /home/oracle/scripts/RMAN_Hotbackup.ksh ARCH > /tmp/RMAN_ARCH.log 2>&1

    ARCH Backup Reruns and Completes

    After the cron fix, the ARCH backup was immediately re-run manually to clear the remaining backlog and validate the fix end-to-end:

    . /home/oracle/.bash_profile
    /home/oracle/scripts/RMAN_Hotbackup.ksh ARCH

    The backup completed successfully. RMAN backed up accumulated archived logs, marked them as obsolete per retention policy, and removed them from the FRA — freeing additional space beyond what the manual ASMCMD deletion had already recovered.

    Preventive Measures Put in Place

    1. Fix the cron environment — all RMAN jobs now source ~/.bash_profile before executing.
    2. RMAN exit code alerting — script updated to email the DBA team on any non-zero RMAN exit status.
    3. FRA monitoring at 70% threshold — SQL script runs every 30 minutes via cron and alerts when FRA crosses 70%, giving enough runway before the database is impacted.
    4. FRA sized on measured data — 400 GB based on actual peak batch redo (30–50 GB/hr), not an arbitrary estimate.
    5. RAC: always use SID=’*’ — and always verify ASM diskgroup free space before increasing the FRA limit.

    Key Takeaways for Oracle DBAs

    • ORA-00257 always points to the FRA being full — check v$recovery_file_dest and v$recovery_area_usage immediately.
    • When RMAN cannot run against a full FRA, use ASMCMD to manually delete older archive logs — then run CROSSCHECK and DELETE EXPIRED to resync the catalog.
    • db_recovery_file_dest_size is dynamic — increase it online without a restart. Always confirm ASM diskgroup free space first.
    • Use SID='*' in RAC — applies the parameter change to all instances simultaneously.
    • The archiver restarts automatically after FRA space is freed — no manual ARCn intervention needed.
    • Silent cron failures are dangerous — always validate Oracle environment variables in cron context, and capture RMAN exit codes with alerting.
    • Monitor FRA proactively at 70% — this gives enough runway for corrective action before hitting 100%.
    • After a manual ASMCMD deletion, always follow up with a proper RMAN backup run to leave the FRA in a consistent state.
    • Analyse redo generation patterns — v$archived_log reveals batch spikes that should directly inform FRA sizing decisions.

    Conclusion

    A Stuck Archiver on a production RAC database is a high-severity incident, but a structured approach resolves it quickly. The immediate fix required two steps: manually deleting archived logs via ASMCMD to unblock the archiver, and increasing db_recovery_file_dest_size online to prevent immediate recurrence.

    The deeper fix was identifying why the RMAN ARCH backup had been silently failing for multiple nights — a missing Oracle environment in the cron context. Once found, the fix was a single line in crontab. Rerunning the backup manually and watching it complete successfully, with FRA usage dropping as a result, confirmed the incident was fully resolved rather than just patched.

    The combination of a corrected cron environment, RMAN exit code alerting, and proactive FRA monitoring at 70% ensures this class of incident does not repeat.

    Syed Anwar Ahmed | Oracle Apps DBA