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
- Undelete/restore the resource if within the retention window, then retry the modification
- Recreate the resource and repoint the workload
- Stop the stale writer (check which process/tenant still references the name)
- 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
- Coordinate DDL/deletes with all writers
- Track soft-delete retention windows
- Alert when workloads target deleted resources
- Prefer recreate over modify for deleted resources
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
- attempted to create a resource that already exists
- {0}
- Adding a new database would exceed limit of
- auto field family exists
- buffer too short: expected at least
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)