nextcloud/server · error · Error

Failed to delete tag for file

Error message

Failed to delete tag for file

What it means

Thrown by deleteTagForFile() when the DELETE on /systemtags-relations/files/{fileId}/{tagId} fails, i.e. detaching a tag from a file. The relation must exist and the user needs assign rights on the tag; the original WebDAVClientError is chained as `cause`.

Source

Thrown at apps/systemtags/src/services/files.ts:85

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

/**
 * Delete a tag for a given file (by id).
 *
 * @param tag - The tag to delete
 * @param fileId - The id of the file to delete the tag for
 */
export async function deleteTagForFile(tag: TagWithId, fileId: number): Promise<void> {
	const path = '/systemtags-relations/files/' + fileId + '/' + tag.id
	try {
		await davClient.deleteFile(path)
	} catch (error) {
		logger.error(t('systemtags', 'Failed to delete tag for file'), { error })
		throw new Error(t('systemtags', 'Failed to delete tag for file'), { cause: error })
	}
}

View on GitHub (pinned to ecdeb153ff)

Solutions

  1. Treat 404 from the cause chain as success (the desired end state already holds) and refresh the file's tag list
  2. Verify the tag list shown is fresh — refetch fetchTagsForFile(fileId) before offering the remove action
  3. Check assign permission (canAssign) before enabling the detach control
  4. On 401 re-authenticate and retry once

Example fix

// before
await deleteTagForFile(tag, fileId) // throws when already detached

// after
try {
	await deleteTagForFile(tag, fileId)
} catch (e) {
	if ((e.cause as WebDAVClientError)?.response?.status === 404) {
		// relation already gone — nothing to do
	} else throw e
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
	await deleteTagForFile(tag, fileId)
} catch (error) {
	const status = (error.cause as WebDAVClientError | undefined)?.response?.status
	if (status === 404) {
		// relation already removed — desired state reached, refresh UI
	} else throw error
}

Prevention

When it happens

Trigger: DELETE failing with 404 when the tag is not currently attached (already removed — stale sidebar state), 403 when the user may not modify the file's tags, 401 on session expiry, or network/maintenance-mode failures.

Common situations: Untagging from a stale sidebar where the relation was already removed in another tab; two clients detaching the same tag concurrently; user without assign permission on an admin tag.

Related errors


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