GitLab: why the comment or the thread was refused
Comments on a merge request go through GitLab's discussions API: a new thread (POST /projects/:id/merge_requests/:iid/discussions, with position for lines of the diff), a reply (…/discussions/:discussion_id/notes), resolving or reopening a thread (PUT …/discussions/:discussion_id with resolved), and applying a suggested change (PUT /projects/:id/suggestions/:id/apply). All of this is from GitLab's source (lib/api/discussions.rb, lib/api/helpers/notes_helpers.rb, lib/api/suggestions.rb, and the note and suggestion models and policies) and its documentation, read on October 24, 2026.
A new comment
- 403
{"message":"403 Forbidden"}: your account may not comment on this merge request. GitLab's permissions page lists commenting on merge requests from the Planner role up. When someone has locked the discussion, only members of the project may comment. - 400
Note {:line_code=>["can't be blank", "must be a valid line code"]}(a comment on lines of the diff): GitLab did not find the line you named in that version of the diff. Public reports quote it this way; a server on Ruby 3.4, which GitLab's source uses now, writes the same answer asNote {line_code: [...]}. From the source and the documentation, the usual causes: the three commits inposition(base_sha,start_sha,head_sha) are not a version of this merge request; the line number is on the wrong side; or an unchanged line got only one ofold_lineandnew_line(it needs both). - 400
Note {:position=>["is incomplete"]}: a part ofpositionis missing, such as one of the three commits or the file's path.
A token without the api scope is refused with 403 too, but that answer says insufficient_scope; see which scope to add.
A reply
- 404
{"message":"404 Discussion Not Found"}: this merge request has no thread with that ID that you can read. - 400
Replies to system notes are not allowed.: the thread starts with one of GitLab's own records (such as "added 2 commits"), and on a merge request those take no replies. - 403: as for a new comment.
Resolving or reopening a thread: 403 with nothing more
{"message":"403 Forbidden"} has two causes in the source, and the answer is the same for both:
- Your account may not resolve it. GitLab's documentation says resolving a thread needs the Developer, Maintainer or Owner role, or being the author of the merge request; in the source, whoever started the thread may resolve it too. When the discussion is locked, only members of the project may.
- It cannot be resolved at all. A standard comment, one nobody has replied to as a thread, is never resolvable (the documentation: it becomes a thread once someone replies), and neither are GitLab's own records. The API answers these with the same 403, not with a 400.
A thread ID that does not exist answers {"message":"404 Discussion Not Found"}.
Applying a suggestion
- 403
{"message":"403 Forbidden"}: applying commits the change to the source branch, and in the source it needs permission to push to that branch (in a fork, the fork's). - 404
Suggestion is not applicable as the suggestion was not found. - 400, with the reason in GitLab's words, among them:
Can't apply this suggestion.: it is already applied.This merge request was merged. To apply this suggestion, edit this file directly.(or…is closed…)Can't apply as the source branch was deleted.Can't apply as this line was changed in a more recent version.(these linesfor several): a newer push changed the lines.A file has been changed.: the source branch has a newer commit than the version the suggestion was made on.This suggestion already matches its content.
Where it stands
curl -H "PRIVATE-TOKEN: your-token" "https://gitlab.com/api/v4/projects/group%2Fproject/merge_requests/42/discussions"
Each thread has individual_note (true for a standard comment), and each of its notes has resolvable, resolved and system (one of GitLab's own records). The merge request itself (…/merge_requests/42) has discussion_locked and diff_refs, the three commits of its latest version. Use your own server's address instead of gitlab.com.
What to do
- 400 "line_code": take the three commits from the merge request's
diff_refs, give an added line'snew_line, a removed line'sold_line, and both for an unchanged line. - 403 on a comment or a reply: if
discussion_lockedis true, ask a member to unlock it or to comment; otherwise ask a maintainer for a role that may comment. - 403 on resolving: if
resolvableis false, there is nothing to resolve: reply to the comment to make it a thread. Otherwise ask the merge request's author, or someone with the Developer role or above. - 400 on applying: refresh and look at the newer version; if the suggestion no longer fits, edit the file directly. 403: ask someone who may push to the source branch.
GitLab merge requests in IntelliJ IDEA
Merge Request Inbox for GitLab, a plugin by Lesstep for JetBrains IDEs 2024.1 or later, comments on a merge request or on lines of its diff (a range of lines, or the range's last line when GitLab refuses the range), replies, resolves and reopens threads, and applies suggested changes. It offers Resolve only on threads GitLab says can be resolved, offers Apply only while GitLab would apply the suggestion, and leaves GitLab's own records out. When GitLab refuses, it says so: for 403, that your role in the project or its settings may not let your account do it, with GitLab's words; other refusals in GitLab's words. Reading is free; approving, commenting and merging are Pro (US$1.50 a month, with a 30-day trial).
GITLAB is a trademark of GitLab Inc.; IntelliJ IDEA is a trademark of JetBrains s.r.o. This page is not affiliated with or endorsed by GitLab Inc. or JetBrains.
More: GitLab approval refused (401, 409) · GitLab merge refused (405, 409, 422) · GitLab "insufficient_scope" · GitLab 401 "invalid_token" · GitLab 404 "Project Not Found" · GitLab merge request not created (409, 422, 400) · GitLab rebase refused or failed (403, 409) · GitLab merge request list refused (400, 404) · GitLab merge request changes cut short ("1000+", too_large) · GitLab 429 "Retry later" (rate limits) · GitLab "compare_timeout": true (diff limits) · GitLab merge request plugins for IntelliJ IDEA, compared · 日本語