go-gitea/gitea · error
Failed to update issue title: ${resp.statusText}
Error message
Failed to update issue title: ${resp.statusText} What it means
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.
Source
Thrown at web_src/js/features/repo-issue.ts:410
issueTitleEditor.querySelector('.ui.cancel.button')!.addEventListener('click', () => {
hideElem(issueTitleEditor);
hideElem('#pull-desc-editor');
showElem(issueTitleDisplay);
showElem('#pull-desc-display');
});
const pullDescEditor = document.querySelector('#pull-desc-editor'); // it may not exist for a merged PR
const prTargetUpdateUrl = pullDescEditor?.getAttribute('data-target-update-url');
const editSaveButton = issueTitleEditor.querySelector('.ui.primary.button')!;
issueTitleEditor.addEventListener('submit', async (e) => {
e.preventDefault();
const newTitle = issueTitleInput.value.trim();
try {
if (newTitle && newTitle !== oldTitle) {
const resp = await POST(editSaveButton.getAttribute('data-update-url')!, {data: new URLSearchParams({title: newTitle})});
if (!resp.ok) {
throw new Error(`Failed to update issue title: ${resp.statusText}`);
}
}
if (prTargetUpdateUrl) {
const newTargetBranch = document.querySelector('#pull-target-branch')!.getAttribute('data-branch');
const oldTargetBranch = document.querySelector('#branch_target')!.textContent;
if (newTargetBranch !== oldTargetBranch) {
const resp = await POST(prTargetUpdateUrl, {data: new URLSearchParams({target_branch: String(newTargetBranch)})});
if (!resp.ok) {
throw new Error(`Failed to update PR target branch: ${resp.statusText}`);
}
}
}
ignoreAreYouSure(issueTitleEditor);
window.location.reload();
} catch (error) {
console.error(error);
showErrorToast(errorMessage(error));
}View on GitHub (pinned to 43ace7cc8a)
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
Example fix
// before
const resp = await POST(editSaveButton.getAttribute('data-update-url')!, {data: new URLSearchParams({title: newTitle})});
if (!resp.ok) {
throw new Error(`Failed to update issue title: ${resp.statusText}`);
}
// after (include status code and server message for diagnosis)
const resp = await POST(editSaveButton.getAttribute('data-update-url')!, {data: new URLSearchParams({title: newTitle})});
if (!resp.ok) {
const body = await resp.json().catch(() => null);
throw new Error(`Failed to update issue title: ${resp.status} ${body?.errorMessage ?? resp.statusText}`);
} Defensive patterns
Strategy: try-catch
Validate before calling
// Skip the request entirely when there is nothing to change const newTitle = issueTitleInput.value.trim(); if (!newTitle || newTitle === oldTitle) return;
Try / catch
try {
if (newTitle && newTitle !== oldTitle) {
const resp = await POST(editSaveButton.getAttribute('data-update-url')!, {data: new URLSearchParams({title: newTitle})});
if (!resp.ok) throw new Error(`Failed to update issue title: ${resp.statusText}`);
}
} catch (error) {
console.error(error);
showErrorToast(errorMessage(error)); // shipped pattern: toast, editor stays open, no data loss
} Prevention
- 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
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- Failed to update PR target branch: ${resp.statusText}
- Invalid server response: ${response.status}
- Failed to reload page: ${resp.statusText}
- Unable to render the PDF file
- unable to create directory for log %q: %v
AI-assisted analysis of go-gitea/gitea@43ace7cc8a (2026-08-15).
Data as JSON: /api/errors/e5b4147f3cd8d6a2.
Report an issue: GitHub.