UVM_FATAL "attempted to drop objection count below zero"

In my simulation I observe following messages
UVM_INFO base_test.sv(117) @ 100000.000ns: uvm_test_top [bit_bash_test] Inside Base test shutdown phase end

UVM_FATAL @ 100023.000ns: post_shutdown_objection [OBJTN_ZERO] Object “uvm_test_top.env.agent.wr_agent.driver” attempted to drop objection ‘post_shutdown_objection’ count below zero

The driver component is an UVC which is re-used in different projects and raises and drops objections internally.

Here is my run_phase of the test that I am running ( bit_bash_test )

virtual task run_phase(uvm_phase phase);
     phase.raise_objection(this);
     // create bit_bash sequence here
     bit_bash_seq.start(env.vseqr);
     #10us;
    `uvm_info(get_type_name(), $sformatf("TEST ...Done!"), UVM_LOW)
     phase.drop_objection(this);
  endtask : run_phase

On debugging I observe that the base_test defines shutdown_phase

  virtual task shutdown_phase(uvm_phase phase); 
    phase.raise_objection(this);
    // The below msg executes at 0.000ns
    `uvm_info(get_type_name(), $sformatf("Inside Base test shutdown phase start"), UVM_LOW)
    #100_000ns;  
      // The below msg executes at 100000.000ns as observed in the top
     `uvm_info(get_type_name(), $sformatf("Inside Base test shutdown phase end "), UVM_LOW)
    phase.drop_objection(this);
  endtask: shutdown_phase

On changing the delay from #100us to #200us I observe that the test completes without UVM_FATAL msg

I am aware that coding guidelines dictate that one should either use run_phase or it’s sub-phases ( but not both ). Since the shutdown_phase is defined in base_test , another alterative is to override the shutdown_phase in the extented test that I am running

  virtual task shutdown_phase(uvm_phase phase); 
    `uvm_info(get_type_name(), $sformatf("In shutdown phase"), UVM_LOW)
  endtask: shutdown_phase

So now the shutdown_phase of base_test doesn’t execute i.e no raising / dropping of objections

[1] My confusion is how does the base_test’s shutdown_phase result in the UVM_FATAL message ?

As you have noticed, trying to use sub-phases in parallel with run_phase() can lead to behavior which is difficult to debug. Since you have both run_phase() and shutdown_phase() defined in your test, the two phases will run at the same time (i.e. shutdown_phase() will NOT run after run_phase()), which is probably not what you want. You need to use either run_phase() or all of the desired sub-phases.

Also, your driver should never raise/drop objections. Objections should only be used by the test.