nextcloud/server · error · Error

Failed to delete tag

Error message

Failed to delete tag

What it means

Thrown by deleteTag() when the DELETE request on /systemtags/{id} fails. Deleting a system tag is an instance-wide operation with permission requirements, and any DAV failure (401/403/404/5xx or network) is wrapped into this error with the original WebDAVClientError as `cause`.

Source

Thrown at apps/systemtags/src/services/api.ts:156

	} catch (error) {
		logger.error(t('systemtags', 'Failed to update tag'), { error })
		throw new Error(t('systemtags', 'Failed to update tag'), { cause: error })
	}
}

/**
 * Delete a tag.
 *
 * @param tag - The tag to delete
 */
export async function deleteTag(tag: TagWithId): Promise<void> {
	const path = '/systemtags/' + tag.id
	try {
		await davClient.deleteFile(path)
		emit('systemtags:tag:deleted', tag)
	} catch (error) {
		logger.error(t('systemtags', 'Failed to delete tag'), { error })
		throw new Error(t('systemtags', 'Failed to delete tag'), { cause: error })
	}
}

type TagObject = {
	id: number
	type: string
}

type TagObjectResponse = {
	etag: string
	objects: TagObject[]
}

/**
 * Get the objects for a tag.
 *
 * @param tag - The tag to get the objects for
 * @param type - The type of the objects

View on GitHub (pinned to ecdeb153ff)

Solutions

  1. Check (error.cause as WebDAVClientError)?.response?.status: treat 404 as already-deleted (refresh the list and continue), 403 as missing permission, 401 as session expiry
  2. Verify the tag still exists with fetchTag(tag.id) before showing a destructive confirmation dialog
  3. For admin operations ensure confirmPassword() ran before the DAV call
  4. Check the server log if the cause status is 5xx

Example fix

// before
await deleteTag(tag) // unhandled 404 when tag was already deleted

// after
try {
	await deleteTag(tag)
} catch (e) {
	if ((e.cause as WebDAVClientError)?.response?.status === 404) {
		// already gone — remove from UI and move on
		emit('systemtags:tag:deleted', tag)
	} else throw e
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
	await deleteTag(tag)
} catch (error) {
	const status = (error.cause as WebDAVClientError | undefined)?.response?.status
	if (status === 404) {
		// already deleted — treat as success and update the UI
	} else throw error
}

Prevention

When it happens

Trigger: DELETE /systemtags/{tagId} failing: 403 (the user lacks admin rights to delete the tag — deleting affects every user since tags are global), 404 (tag already removed elsewhere), 401 (expired session), 503 (maintenance mode), or connectivity loss.

Common situations: Non-admin attempting to delete a global tag from the tag management UI; the tag already deleted from another session (stale list); removing a tag that files still carry; server in maintenance during upgrade.

Related errors


AI-assisted analysis of nextcloud/server@ecdeb153ff (2026-08-17). Data as JSON: /api/errors/db5a1fe05b5d68f0. Report an issue: GitHub.