nextcloud/server · error · Error

Failed to update tag

Error message

Failed to update tag

What it means

Thrown by updateTag() when the PROPPATCH request to /systemtags/{id} fails. The tag is updated by sending a property-update XML body (display-name, user-visible, user-assignable, color) and any DAV-level failure — 401, 403, 404, 5xx or a network error — is wrapped into this error with the original WebDAVClientError as `cause`.

Source

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

		<d:set>
			<d:prop>
				<oc:display-name>${tag.displayName}</oc:display-name>
				<oc:user-visible>${tag.userVisible}</oc:user-visible>
				<oc:user-assignable>${tag.userAssignable}</oc:user-assignable>
				<nc:color>${tag?.color || null}</nc:color>
			</d:prop>
		</d:set>
	</d:propertyupdate>`

	try {
		await davClient.customRequest(path, {
			method: 'PROPPATCH',
			data,
		})
		emit('systemtags:tag:updated', tag)
	} 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 })
	}
}

View on GitHub (pinned to ecdeb153ff)

Solutions

  1. Inspect (error.cause as WebDAVClientError)?.response?.status: 404 → refetch the tag list (the tag is gone); 403 → the user cannot edit this tag; 401 → re-authenticate
  2. Refetch the tag with fetchTag(tag.id) before opening the edit dialog to avoid editing stale state
  3. Run confirmPassword() from @nextcloud/password-confirmation before admin-level tag edits
  4. If the cause status is 5xx, check the Nextcloud server log (maintenance mode or server-side error)

Example fix

// before
const tag = { id: 12, displayName: 'renamed', userVisible: true, userAssignable: true }
await updateTag(tag as TagWithId)

// after
try {
	await updateTag(tag as TagWithId)
} catch (e) {
	const status = (e.cause as WebDAVClientError)?.response?.status
	if (status === 404) emit('systemtags:tag:deleted-stale', tag) // refresh list
	else throw e
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Optional liveness pre-check
import { fetchTag, updateTag } from './services/api.ts'

async function safeUpdateTag(tag: TagWithId) {
	await fetchTag(tag.id) // throws 'Failed to load tag' if it no longer exists
	await updateTag(tag)
}

Try / catch

try {
	await updateTag(tag)
} catch (error) {
	const status = (error.cause as WebDAVClientError | undefined)?.response?.status
	if (status === 404) { /* tag deleted elsewhere — refetch list */ }
	else if (status === 403) { /* no edit rights on this tag */ }
	else throw error
}

Prevention

When it happens

Trigger: PROPPATCH /systemtags/{tagId} failing: 403 when the caller lacks edit rights on the tag (editing tags generally requires admin/creation-level permission), 404 when the tag was deleted after the list was loaded, 401 after session expiry, or 503 while the server is in maintenance mode.

Common situations: Non-admin user renaming a tag they cannot manage; tag deleted in another tab/session and the edit dialog still open; session expired during long-open admin settings; concurrent edits where another client already removed the tag.

Related errors


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