
Action Hook since 2.0.0
delete_attachment
Fires just before an attachment and its files are deleted
Description
delete_attachment is your last chance to read an attachment's post meta or file path before wp_delete_attachment() removes the database row and the files on disk.
When it runs
Inside wp_delete_attachment(), before the attachment post, its meta, and its files are removed.
Signature
do_action( 'delete_attachment', int $post_id, WP_Post $post );Parameters
post_idint — The ID of the attachment being deleted.postWP_Post — The attachment post object, before deletion.
Examples
Basic
add_action( 'delete_attachment', function( $post_id ) {
error_log( 'Deleting attachment: ' . $post_id );
} );Log every attachment deletion.
Real case
add_action( 'delete_attachment', function( $post_id ) {
$file = get_attached_file( $post_id );
do_action( 'my_cdn_purge', $file );
}, 10, 1 );Purge a CDN-cached copy of the file before WordPress deletes the local original.
Edge case
add_action( 'delete_attachment', function( $post_id, $post ) {
if ( 'image/' !== substr( $post->post_mime_type, 0, 6 ) ) {
return;
}
}, 10, 2 );Filter by mime type when the cleanup logic only applies to images.
Common Use Cases
- Purge CDN or cache entries tied to the file
- Clean up related custom meta or database rows
- Log deletions for an audit trail
- Block deletion of protected files (via a related filter, not this action)
Common mistakes
- Trying to prevent the deletion from inside this action — it's an action, not a filter, so it can't stop the delete; use the wp_delete_file filter for file-path-level control instead
Related hooks
FAQ
Can I cancel a deletion from inside delete_attachment?
No — this action fires as notification, not permission. It can't stop the delete from proceeding.
Is the file still on disk when this fires?
Yes — the file and its generated sizes are still present; this is the last point where get_attached_file() returns a valid path.
Source: wp-includes/post.php