{"record":{"id":"1d8847e7ef415d3c","repo":"nextcloud/server","slug":"failed-to-delete-tag-for-file","errorCode":null,"errorMessage":"Failed to delete tag for file","messagePattern":"Failed to delete tag for file","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/systemtags/src/services/files.ts","lineNumber":85,"sourceCode":"\t} catch (error) {\n\t\tlogger.error(t('systemtags', 'Failed to set tag for file'), { error })\n\t\tthrow new Error(t('systemtags', 'Failed to set tag for file'), { cause: error })\n\t}\n}\n\n/**\n * Delete a tag for a given file (by id).\n *\n * @param tag - The tag to delete\n * @param fileId - The id of the file to delete the tag for\n */\nexport async function deleteTagForFile(tag: TagWithId, fileId: number): Promise<void> {\n\tconst path = '/systemtags-relations/files/' + fileId + '/' + tag.id\n\ttry {\n\t\tawait davClient.deleteFile(path)\n\t} catch (error) {\n\t\tlogger.error(t('systemtags', 'Failed to delete tag for file'), { error })\n\t\tthrow new Error(t('systemtags', 'Failed to delete tag for file'), { cause: error })\n\t}\n}\n","sourceCodeStart":67,"sourceCodeEnd":88,"githubUrl":"https://github.com/nextcloud/server/blob/ecdeb153ffdf227235c9a7e2d13dbe0f9c817bc3/apps/systemtags/src/services/files.ts#L67-L88","documentation":"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`.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Treat 404 from the cause chain as success (the desired end state already holds) and refresh the file's tag list","Verify the tag list shown is fresh — refetch fetchTagsForFile(fileId) before offering the remove action","Check assign permission (canAssign) before enabling the detach control","On 401 re-authenticate and retry once"],"exampleFix":"// before\nawait deleteTagForFile(tag, fileId) // throws when already detached\n\n// after\ntry {\n\tawait deleteTagForFile(tag, fileId)\n} catch (e) {\n\tif ((e.cause as WebDAVClientError)?.response?.status === 404) {\n\t\t// relation already gone — nothing to do\n\t} else throw e\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n\tawait deleteTagForFile(tag, fileId)\n} catch (error) {\n\tconst status = (error.cause as WebDAVClientError | undefined)?.response?.status\n\tif (status === 404) {\n\t\t// relation already removed — desired state reached, refresh UI\n\t} else throw error\n}","preventionTips":["Treat 404 as success — detach is idempotent in effect","Refetch fetchTagsForFile(fileId) when the sidebar regains focus to avoid stale relations","Disable the remove action while a request is pending"],"tags":["systemtags","webdav","delete","tag-assignment","typescript"],"backgroundTag":"webdav-delete-failed","analyzedSha":"ecdeb153ffdf227235c9a7e2d13dbe0f9c817bc3","analyzedAt":"2026-08-17T01:36:13.386Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}