select open change scope Open full search

PG.CENTER connects PostgreSQL documentation, reference, and ecosystem knowledge. Maintained by Pigsty.

SQLSTATE / CLASS 2B · DEPENDENT PRIVILEGE DESCRIPTORS STILL EXIST

dependent_objects_still_exist

SQLSTATE
2BP01
Condition name
dependent_objects_still_exist
Class
Dependent Privilege Descriptors Still Exist
Source macro
ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST
Evidence
Observed at runtime in the source evidence
Analysis & operational context

English SQLSTATE atlas: authored explanations and source/runtime evidence are separate from the manual definitions. View source ↗

<h1>2BP01 — dependent_objects_still_exist</h1>

At a glance

2BP01 means a DROP or related catalog operation would remove an object that other database objects still require. The useful repair is dependency-aware: identify the dependent object, decide whether it should be removed or retained, and only then retry the original operation.

Meaning

The dependency walker emits 2BP01 for a blocked object operation. In the representative path, a view depends on a table, so DROP TABLE cannot proceed. The primary message, DETAIL, and CASCADE hint are dynamically assembled from object descriptions and the dependency graph. 2BP01 is about dependent objects; 2B000 is a separate dependent-privilege-descriptor condition.

Diagnosis

Capture SQLSTATE, primary message, DETAIL, and HINT together. The DETAIL identifies the dependent view in the selected path. Inspect the view definition and dependency metadata before choosing a repair; pg_depend and pg_get_viewdef() help explain why the object is retained. In the selected explicit BEGIN block, this ERROR puts the connection in INERROR until ROLLBACK; an autocommit statement has no surrounding block to preserve. Catalog queries issued through the failed explicit block will not provide a clean diagnosis.

Response

Rollback the failed explicit transaction. If the view is intentionally disposable, drop that view first and then the table; if it is part of the schema contract, preserve it and choose a different migration. CASCADE is a deliberate request to remove dependent objects and can exceed the intended change, so the HINT is not an instruction to apply it automatically. After a dependency-aware repair, rerun the complete DDL plan and verify the surviving objects.

Messages

The selected source branch uses cannot drop %s because other objects depend on it, a dynamic internal DETAIL, and Use DROP ... CASCADE to drop the dependent objects too. The object descriptions and dependency list are runtime values; do not treat the DETAIL as a stable single-object template or assume every 2BP01 path has this exact wording.

Representative case

The runner reads this dependency sequence from verify/cases/2BP01/snippets.json (SHA-256 899e4fd9fb002fc293bd9efee0204e4f2622968c6d9460ad05eb9a0ebd3bac69). It uses an explicit BEGIN/ROLLBACK for the failed DROP and then removes the known view before its table, without CASCADE. See the public case export and structured evidence.

CREATE TABLE base_items(id integer PRIMARY KEY, payload text NOT NULL);
CREATE VIEW dependent_view AS SELECT id, payload FROM base_items;
BEGIN;
DROP TABLE base_items;
ROLLBACK;
DROP VIEW dependent_view;
DROP TABLE base_items;
SELECT to_regclass('base_items'), to_regclass('dependent_view');

The registry names are qualified by the runner inside a private schema. The final to_regclass check returns two nulls, proving that the intended objects were removed rather than silently cascading through an unknown graph.

The selected case observed 2BP01 on PostgreSQL 18.6 and 10.21. DROP TABLE reported the dependent view in DETAIL and suggested CASCADE; the explicit block was INERROR, ROLLBACK restored IDLE, and intentionally dropping the view first allowed the table to be removed.

Versions

The catalogue records this condition from the early historical boundary through the formal snapshots. The fixed 18.6 source includes dependency, shared-dependency, role, privilege, typed-table, and tablespace branches; the runtime case covers one ordinary view-to-table dependency on 18.6 and 10.21. Do not infer that a CASCADE hint is equally safe for all branches.

Sources

  • src.errcodes.18.6 (SHA-256 6e8de346643ba84aa3c9c6a73360acfc7b2dfb89162c06c08ce9bf5bcd5bbcba)
  • src.dependency.18.6 (SHA-256 1878f848dae03e08424a47a09508f3443227ad67c4bc5e0aba3ec9655d015b74)
  • DROP TABLE documentation · local call scan src.calls.REL_18_6 (SHA-256 9ee8a0e81d8f0825c5c1ae45583439859a26e602bdd4ce2f2a62aa278867ccbf)

Source evidence

Evidence belongs to the frozen source and runtime versions listed here. It is not a runtime verification of the selected manual version.

2BP01 is the dependent_objects_still_exist condition in Class 2B.

Method: Read the fixed errcodes.txt row and macro mapping.

Limits: Other dependent-privilege and typed-object paths use the same condition with different dynamic messages.

src.errcodes.18.6

The dependency walker reports that an object cannot be dropped while other objects depend on it and supplies a CASCADE hint.

Method: Trace reportDependentObjects and its dynamic DETAIL/HINT assembly.

Limits: DETAIL names the dependency graph dynamically; it is not a fixed format for every object kind.

src.dependency.18.6 src.calls.REL_18_6

A safe repair identifies the dependent view and drops it intentionally before dropping its base table; CASCADE is an explicit policy choice, not a universal repair.

Method: Use a view-to-table dependency and the shared registry repair sequence.

Limits: Other dependency types and ownership/privilege checks may require a different order or privileges.

doc.drop.18.6

The selected 2BP01 case passed on PostgreSQL 18.6 and 10.21 with the structured SQLSTATE, transaction-state, and repair assertions recorded in the runtime entries.

Method: Read the selected runner summaries and raw outputs tied to the shared snippet registry.

Limits: The INERROR then IDLE assertion belongs to the selected explicit BEGIN/ROLLBACK block; autocommit statements have no surrounding block to preserve.

runtime.2BP01-batch34-final-20260909.latest runtime.2BP01-batch34-final-20260909.pg10

Message templates

ERROR · message.dependent-object

Primary

cannot drop %s because other objects depend on it

Detail

%s (dynamic internal detail)

Hint

Use DROP ... CASCADE to drop the dependent objects too.

Object descriptions and dependency detail are dynamically assembled.

Reproduction & repair cases

dependent_object_drop_recovery · PG 10, 18

Preconditions

  • A runner-owned disposable target is provisioned.

Trigger: Create a view that depends on a table, attempt DROP TABLE inside an explicit transaction, then drop the view first and the table.

Expected assertions

  • SQLSTATE is 2BP01
  • The diagnostic names dependent objects
  • The failed transaction is INERROR until ROLLBACK
  • Dropping the dependent view first removes both objects without CASCADE

Repair: Rollback the failed DROP, inspect the named dependent objects, and remove them in an intentional dependency order.

Cleanup: Drop the case schema with an owner connection.

Recorded runtime evidence

18.6 (Homebrew) · passed

Run: 2BP01-batch34-final-20260909

{
  "repair": {
    "remaining_relations": [
      null,
      null
    ]
  },
  "primary": "cannot drop table c2bp01_dependent_object_drop_recovery.base_items because other objects depend on it",
  "severity": "ERROR",
  "sqlstate": "2BP01",
  "statuses": {
    "after_error": "INERROR",
    "after_repair": "IDLE",
    "after_rollback": "IDLE"
  },
  "connection_autocommit": true
}
10.21 (Debian 10.21-1.pgdg90+1) · passed

Run: 2BP01-batch34-final-20260909

{
  "repair": {
    "remaining_relations": [
      null,
      null
    ]
  },
  "primary": "cannot drop table c2bp01_dependent_object_drop_recovery.base_items because other objects depend on it",
  "severity": "ERROR",
  "sqlstate": "2BP01",
  "statuses": {
    "after_error": "INERROR",
    "after_repair": "IDLE",
    "after_rollback": "IDLE"
  },
  "connection_autocommit": true
}

Definition snapshot: english-manuals:9cbb6552a6065c9b38ec1666f29… · English manual source