influxdata/influxdb · error · CatalogError

attempted to modify resource that was already deleted

Error message

attempted to modify resource that was already deleted: {0}

What it means

CatalogError::AlreadyDeleted(String) is thrown when an operation tries to modify a catalog resource that was already (soft-)deleted. The catalog keeps deleted resources for a retention window to allow undelete, and any mutation other than restore is rejected. The payload names the deleted resource.

Solutions

  1. Undelete/restore the resource if within the retention window, then retry the modification
  2. Recreate the resource and repoint the workload
  3. Stop the stale writer (check which process/tenant still references the name)
  4. Match on CatalogError::AlreadyDeleted and treat as a terminal condition for the workload

Example fix

// before
catalog.create_table("mydb", "t", schema, Linear).await?;
// after
if db.table_exists("t") { /* ensure not soft-deleted first */ }
// restore deleted table via the undelete API before re-creating
Defensive patterns

Strategy: try-catch

Validate before calling

// Rust: confirm resource is live before modifying
let db = catalog.db("mydb")?;
assert!(!db.deleted());

Type guard

fn is_already_deleted(err: &CatalogError) -> Option<&str> {
    match err { CatalogError::AlreadyDeleted(name) => Some(name), _ => None }
}

Try / catch

match catalog.alter_database("mydb", ops).await {
    Err(CatalogError::AlreadyDeleted(name)) => {
        eprintln!("{name} is deleted; undelete or recreate before modifying");
    }
    other => other?,
}

Prevention

When it happens

Trigger: Writing to or altering a database/table after DELETE /api/v3/configure/database?db=name; updating a trigger or token that has been deleted; hard-delete window expired and a modify arrives.

Common situations: Applications still writing to a database another team decommissioned; scripts deleting then re-creating without waiting for the retention window; stale DDL in migrations.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of influxdata/influxdb@06200ef96b (2026-09-19). Data as JSON: /api/errors/d16bac19cf369569. Report an issue: GitHub.

Appendix: source

Thrown at influxdb3_catalog/src/error.rs:56

#[derive(Debug, thiserror::Error)]
pub enum CatalogError {
    #[error(transparent)]
    Enterprise(#[from] EnterpriseCatalogError),

    #[error("object store error: {0:?}")]
    ObjectStore(#[from] ObjectStoreCatalogError),

    #[error("catalog format error: {0}")]
    Format(#[from] FormatError),

    #[error("attempted to create a resource that already exists")]
    AlreadyExists,

    #[error("the requested resource was not found: {0}")]
    NotFound(String),

    #[error("attempted to modify resource that was already deleted: {0}")]
    AlreadyDeleted(String),

    /// Request is idempotent: no catalog state would change.
    #[error("no catalog changes to apply: {details}")]
    NoCatalogChange { details: String },

    /// Request is invalid.
    #[error("catalog internal error: {details}")]
    Internal { details: String },

    #[error(
        "persisted catalog checkpoint sequence {checkpoint_sequence} is ahead of live catalog sequence {live_sequence}"
    )]
    BackupCheckpointAhead {
        checkpoint_sequence: u64,
        live_sequence: u64,
    },

View on GitHub (pinned to 06200ef96b)