{"record":{"id":"e5b4147f3cd8d6a2","repo":"go-gitea/gitea","slug":"failed-to-update-issue-title-resp-statustext","errorCode":null,"errorMessage":"Failed to update issue title: ${resp.statusText}","messagePattern":"Failed to update issue title: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"web_src/js/features/repo-issue.ts","lineNumber":410,"sourceCode":"  issueTitleEditor.querySelector('.ui.cancel.button')!.addEventListener('click', () => {\n    hideElem(issueTitleEditor);\n    hideElem('#pull-desc-editor');\n    showElem(issueTitleDisplay);\n    showElem('#pull-desc-display');\n  });\n\n  const pullDescEditor = document.querySelector('#pull-desc-editor'); // it may not exist for a merged PR\n  const prTargetUpdateUrl = pullDescEditor?.getAttribute('data-target-update-url');\n\n  const editSaveButton = issueTitleEditor.querySelector('.ui.primary.button')!;\n  issueTitleEditor.addEventListener('submit', async (e) => {\n    e.preventDefault();\n    const newTitle = issueTitleInput.value.trim();\n    try {\n      if (newTitle && newTitle !== oldTitle) {\n        const resp = await POST(editSaveButton.getAttribute('data-update-url')!, {data: new URLSearchParams({title: newTitle})});\n        if (!resp.ok) {\n          throw new Error(`Failed to update issue title: ${resp.statusText}`);\n        }\n      }\n      if (prTargetUpdateUrl) {\n        const newTargetBranch = document.querySelector('#pull-target-branch')!.getAttribute('data-branch');\n        const oldTargetBranch = document.querySelector('#branch_target')!.textContent;\n        if (newTargetBranch !== oldTargetBranch) {\n          const resp = await POST(prTargetUpdateUrl, {data: new URLSearchParams({target_branch: String(newTargetBranch)})});\n          if (!resp.ok) {\n            throw new Error(`Failed to update PR target branch: ${resp.statusText}`);\n          }\n        }\n      }\n      ignoreAreYouSure(issueTitleEditor);\n      window.location.reload();\n    } catch (error) {\n      console.error(error);\n      showErrorToast(errorMessage(error));\n    }","sourceCodeStart":392,"sourceCodeEnd":428,"githubUrl":"https://github.com/go-gitea/gitea/blob/43ace7cc8ad5fa20027b1ca5b3ab5f1134972ed5/web_src/js/features/repo-issue.ts#L392-L428","documentation":"Thrown when saving an edited issue/PR title in the Gitea web UI. The submit handler POSTs the new title to the issue's update URL (data-update-url on the save button, resolving to POST /{owner}/{repo}/issues/{index}/title) and any non-2xx response aborts with the response's statusText, leaving the old title in place.","triggerScenarios":"POST to the title-update endpoint returns non-ok: title is empty or whitespace after server-side trimming (400/422), user lost write permission to the repo or issue (403), the issue index no longer exists or was migrated (404), session/CSRF token expired so the request is rejected (403/419), or an internal error occurred while saving (500).","commonSituations":"Editing a title in one tab while the issue was closed/locked/migrated in another; permissions changed (user demoted from collaborator) while the edit dialog was open; long-idle tab with a stale CSRF token; concurrent edit where the title was already changed by someone else.","solutions":["Confirm the new title is non-empty and actually different from the old one (the handler only sends it when newTitle && newTitle !== oldTitle, but server-side trimming can still reject whitespace-only titles)","Reopen the issue page fresh and retry — this refreshes CSRF tokens and permissions","Check the user still has write/push access to the repository","If it persists, check the Gitea server log for the 500 root cause on the title-update route"],"exampleFix":"// before\nconst resp = await POST(editSaveButton.getAttribute('data-update-url')!, {data: new URLSearchParams({title: newTitle})});\nif (!resp.ok) {\n  throw new Error(`Failed to update issue title: ${resp.statusText}`);\n}\n\n// after (include status code and server message for diagnosis)\nconst resp = await POST(editSaveButton.getAttribute('data-update-url')!, {data: new URLSearchParams({title: newTitle})});\nif (!resp.ok) {\n  const body = await resp.json().catch(() => null);\n  throw new Error(`Failed to update issue title: ${resp.status} ${body?.errorMessage ?? resp.statusText}`);\n}","handlingStrategy":"try-catch","validationCode":"// Skip the request entirely when there is nothing to change\nconst newTitle = issueTitleInput.value.trim();\nif (!newTitle || newTitle === oldTitle) return;","typeGuard":null,"tryCatchPattern":"try {\n  if (newTitle && newTitle !== oldTitle) {\n    const resp = await POST(editSaveButton.getAttribute('data-update-url')!, {data: new URLSearchParams({title: newTitle})});\n    if (!resp.ok) throw new Error(`Failed to update issue title: ${resp.statusText}`);\n  }\n} catch (error) {\n  console.error(error);\n  showErrorToast(errorMessage(error)); // shipped pattern: toast, editor stays open, no data loss\n}","preventionTips":["Validate title is non-empty and actually changed before sending (the handler does; keep it that way)","Read resp.json() errorMessage when present instead of relying on statusText, which is often empty on 500s","Refresh the page before editing issues that may have been closed, migrated, or permission-changed elsewhere"],"tags":["network","http","issues","permissions","gitea-frontend"],"backgroundTag":null,"analyzedSha":"43ace7cc8ad5fa20027b1ca5b3ab5f1134972ed5","analyzedAt":"2026-08-15T09:36:00.065Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}