Repository: semantic-release/gitlab (js)

Issue:
422 (Unprocessable entity) due to missing ref
I am trying to run semantic-release in a gitlab CI job (using gitlab.com version), but getting the following error:

> An error occurred while making a request to the GitLab release API:
HTTPError: Response code 422 (Ref is not specified)

### My `.releasconfig.json` file:

```json
{
  "branches": ["main", "master"],
  "plugins": [
    [
      "@semantic-release/commit-analyzer",
      {
        "preset": "conventionalcommits",
        "releaseRules": [
          { "type": "feat", "release": "minor" },
          { "type": "fix", "release": "patch" },
          { "type": "perf", "release": "patch" },
          { "type": "refactor", "release": "patch" },
          { "type": "docs", "release": "patch" },
          { "type": "ci", "release": "patch" },
          { "type": "test", "release": "patch" },
          { "type": "build", "release": "patch" },
          { "type": "style", "release": "patch" },
          { "scope": "no-release", "release": false }
        ],
        "parserOpts": {
          "noteKeywords": ["BREAKING CHANGE", "BREAKING CHANGES"],
          "headerPattern": "^(?:[^\\w]*\\s)?(\\w+)(?:\\(([^)]*)\\))?:\\s(.*)$",
          "headerCorrespondence": ["type", "scope", "subject"],
          "headerPatternOptions": "u",
          "mergePattern": "^Merge branch.*",
          "mergeCorrespondence": ["subject"]
        },
        "ignoreCommitsWithoutType": true
      }
    ],
    [
      "@semantic-release/release-notes-generator",
      {
        "preset": "conventionalcommits",
        "parserOpts": {
          "noteKeywords": ["BREAKING CHANGE", "BREAKING CHANGES"],
          "headerPattern": "^(?:[^\\w]*\\s)?(\\w+)(?:\\(([^)]*)\\))?:\\s(.*)$",
          "headerCorrespondence": ["type", "scope", "subject"],
          "headerPatternOptions": "u",
          "mergePattern": "^Merge branch.*",
          "mergeCorrespondence": ["subject"]
        },
        "presetConfig": {
          "types": [
            { "type": "feat", "section": "Features" },
            { "type": "fix", "section": "Bug Fixes" },
            { "type": "refactor", "section": "Internal", "hidden": false },
            { "type": "perf", "section": "Performance", "hidden": false },
            { "type": "docs", "section": "Documentation", "hidden": false },
            { "type": "ci", "section": "DevOps", "hidden": false },
            { "type": "test", "section": "Tests", "hidden": false }
          ]
        }
      }
    ],
    "@semantic-release/gitlab"
  ]
}

```


### The complete logs from my CI job:

<details>

<summary>Click to show</summary>

```
> semantic-release --tag-format='${version}'
[4:42:45 PM] [semantic-release] › ℹ  Running semantic-release version 24.2.3
[4:42:45 PM] [semantic-release] › ✔  Loaded plugin "verifyConditions" from "@semantic-release/gitlab"
[4:42:45 PM] [semantic-release] › ✔  Loaded plugin "analyzeCommits" from "@semantic-release/commit-analyzer"
[4:42:45 PM] [semantic-release] › ✔  Loaded plugin "generateNotes" from "@semantic-release/release-notes-generator"
[4:42:45 PM] [semantic-release] › ✔  Loaded plugin "publish" from "@semantic-release/gitlab"
[4:42:45 PM] [semantic-release] › ✔  Loaded plugin "success" from "@semantic-release/gitlab"
[4:42:45 PM] [semantic-release] › ✔  Loaded plugin "fail" from "@semantic-release/gitlab"
[4:42:48 PM] [semantic-release] › ✔  Run automated release from branch main on repository https://elfrontboi:[secure]@gitlab.com/elfrontboi/gitops.git
[4:42:48 PM] [semantic-release] › ✔  Allowed to push to the Git repository
[4:42:48 PM] [semantic-release] › ℹ  Start step "verifyConditions" of plugin "@semantic-release/gitlab"
[4:42:48 PM] [semantic-release] [@semantic-release/gitlab] › ℹ  Verify GitLab authentication (https://gitlab.com/api/v4)
[4:42:48 PM] [semantic-release] › ✔  Completed step "verifyConditions" of plugin "@semantic-release/gitlab"
[4:42:48 PM] [semantic-release] › ℹ  Found git tag 1.2.0 associated with version 1.2.0 on branch main
[4:42:48 PM] [semantic-release] › ℹ  Found 1 commits since last release
[4:42:48 PM] [semantic-release] › ℹ  Start step "analyzeCommits" of plugin "@semantic-release/commit-analyzer"
[4:42:48 PM] [semantic-release] [@semantic-release/commit-analyzer] › ℹ  Analyzing commit: ✨ feat: le fix
[4:42:48 PM] [semantic-release] [@semantic-release/commit-analyzer] › ℹ  The release type for the commit is minor
[4:42:48 PM] [semantic-release] [@semantic-release/commit-analyzer] › ℹ  Analysis of 1 commits complete: minor release
[4:42:48 PM] [semantic-release] › ✔  Completed step "analyzeCommits" of plugin "@semantic-release/commit-analyzer"
[4:42:48 PM] [semantic-release] › ℹ  The next release version is 1.3.0
[4:42:48 PM] [semantic-release] › ℹ  Start step "generateNotes" of plugin "@semantic-release/release-notes-generator"
[4:42:48 PM] [semantic-release] › ✔  Completed step "generateNotes" of plugin "@semantic-release/release-notes-generator"
[4:42:51 PM] [semantic-release] › ✔  Created tag 1.3.0
[4:42:51 PM] [semantic-release] › ℹ  Start step "publish" of plugin "@semantic-release/gitlab"
[4:42:51 PM] [semantic-release] [@semantic-release/gitlab] › ✘  An error occurred while making a request to the GitLab release API:
HTTPError: Response code 422 (Ref is not specified)
    at Request.<anonymous> (file:///builds/elfrontboi/test/gitops/templates/semantic-release/node_modules/got/dist/source/as-promise/index.js:92:42)
    at Object.onceWrapper (node:events:633:26)
    at Request.emit (node:events:530:35)
    at Request._onResponseBase (file:///builds/elfrontboi/test/gitops/templates/semantic-release/node_modules/got/dist/source/core/index.js:609:22)
    at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
    at async Request._onResponse (file:///builds/elfrontboi/test/gitops/templates/semantic-release/node_modules/got/dist/source/core/index.js:649:13) {
  input: undefined,
  code: 'ERR_NON_2XX_3XX_RESPONSE',
  timings: {
    start: 1743439371130,
    socket: 1743439371131,
    lookup: 1743439371131,
    connect: 1743439371131,
    secureConnect: 1743439371131,
    upload: 1743439371131,
    response: 17434393713[32](https://gitlab.com/elfrontboi/test/-/jobs/9579480656#L32),
    end: 1743439371332,
    error: undefined,
    abort: undefined,
    phases: {
      wait: 1,
      dns: 0,
      tcp: 0,
      tls: 0,
      request: 0,
      firstByte: 201,
      download: 0,
      total: 202
    }
  },
  options: {
    request: undefined,
    agent: { http: undefined, https: undefined, http2: undefined },
    h2session: undefined,
    decompress: true,
    timeout: {
      connect: undefined,
      lookup: undefined,
      read: undefined,
      request: undefined,
      response: undefined,
      secureConnect: undefined,
      send: undefined,
      socket: undefined
    },
    prefixUrl: '',
    body: '{"tag_name":"1.3.0","description":"## [1.3.0](https://gitlab.com/elfrontboi/gitops/compare/1.2.0...1.3.0) (2025-03-31)\\n\\n### Features\\n\\n* le fix ([0384e78](https://gitlab.com/elfrontboi/gitops/commit/0384e780c18207234dee570bb1b94543726e4da2))\\n","assets":{"links":[]}}',
    form: undefined,
    json: undefined,
    cookieJar: undefined,
    ignoreInvalidCookies: [secure],
    searchParams: undefined,
    dnsLookup: undefined,
    dnsCache: undefined,
    context: {},
    hooks: {
      init: [],
      beforeRequest: [],
      beforeError: [ [Function (anonymous)] ],
      beforeRedirect: [],
      beforeRetry: [],
      afterResponse: []
    },
    followRedirect: true,
    maxRedirects: 10,
    cache: undefined,
    throwHttpErrors: true,
    username: '',
    password: '',
    http2: [secure],
    allowGetBody: [secure],
    headers: {
      'user-agent': 'got (https://github.com/sindresorhus/got)',
      'private-token': '[secure]',
      'content-type': 'application/json',
      'content-length': '270',
      'accept-encoding': 'gzip, deflate, br'
    },
    methodRewriting: [secure],
    dnsLookupIpVersion: undefined,
    parseJson: [Function: parse],
    stringifyJson: [Function: stringify],
    retry: {
      limit: 3,
      methods: [ 'GET', 'PUT', 'HEAD', 'DELETE', 'OPTIONS', 'TRACE' ],
      statusCodes: [
        408, 413, 429, 500,
        502, 503, 504, 521,
        522, 524
      ],
      errorCodes: [
        'ETIMEDOUT',
        'ECONNRESET',
        'EADDRINUSE',
        'ECONNREFUSED',
        'EPIPE',
        'ENOTFOUND',
        'ENETUNREACH',
        'EAI_AGAIN'
      ],
      maxRetryAfter: undefined,
      calculateDelay: [Function: calculateDelay],
      backoffLimit: Infinity,
      noise: 100
    },
    localAddress: undefined,
    method: 'POST',
    createConnection: undefined,
    cacheOptions: {
      shared: undefined,
      cacheHeuristic: undefined,
      immutableMinTimeToLive: undefined,
      ignoreCargoCult: undefined
    },
    https: {
      alpnProtocols: undefined,
      rejectUnauthorized: undefined,
      checkServerIdentity: undefined,
      certificateAuthority: undefined,
      key: undefined,
      certificate: undefined,
      passphrase: undefined,
      pfx: undefined,
      ciphers: undefined,
      honorCipherOrder: undefined,
      minVersion: undefined,
      maxVersion: undefined,
      signatureAlgorithms: undefined,
      tlsSessionLifetime: undefined,
      dhparam: undefined,
      ecdhCurve: undefined,
      certificateRevocationLists: undefined
    },
    encoding: undefined,
    resolveBodyOnly: [secure],
    isStream: [secure],
    responseType: 'text',
    url: URL {
      href: 'https://gitlab.com/api/v4/projects/68513935/releases',
      origin: 'https://gitlab.com',
      protocol: 'https:',
      username: '',
      password: '',
      host: 'gitlab.com',
      hostname: 'gitlab.com',
      port: '',
      pathname: '/api/v4/projects/68513935/releases',
      search: '',
      searchParams: URLSearchParams {},
      hash: ''
    },
    pagination: {
      transform: [Function: transform],
      paginate: [Function: paginate],
      filter: [Function: filter],
      shouldContinue: [Function: shouldContinue],
      countLimit: Infinity,
      backoff: 0,
      requestLimit: 10000,
      stackAllItems: [secure]
    },
    setHost: true,
    maxHeaderSize: undefined,
    signal: undefined,
    enableUnixSockets: [secure]
  },
  [cause]: {}
}
[4:42:51 PM] [semantic-release] › ✘  Failed step "publish" of plugin "@semantic-release/gitlab"
[4:42:51 PM] [semantic-release] › ✘  An error occurred while running semantic-release: HTTPError: Response code 422 (Ref is not specified)
    at Request.<anonymous> (file:///builds/elfrontboi/test/gitops/templates/semantic-release/node_modules/got/dist/source/as-promise/index.js:92:42)
    at Object.onceWrapper (node:events:6[33](https://gitlab.com/elfrontboi/test/-/jobs/9579480656#L33):26)
    at Request.emit (node:events:530:35)
    at Request._onResponseBase (file:///builds/elfrontboi/test/gitops/templates/semantic-release/node_modules/got/dist/source/core/index.js:609:22)
    at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
    at async Request._onResponse (file:///builds/elfrontboi/test/gitops/templates/semantic-release/node_modules/got/dist/source/core/index.js:649:13) {
  input: undefined,
  code: 'ERR_NON_2XX_3XX_RESPONSE',
  timings: {
    start: 174[34](https://gitlab.com/elfrontboi/test/-/jobs/9579480656#L34)39371130,
    socket: 1743439371131,
    lookup: 1743439371131,
    connect: 1743439371131,
    secureConnect: 1743439371131,
    upload: 1743439371131,
    response: 1743439371332,
    end: 1743439371332,
    error: undefined,
    abort: undefined,
    phases: {
      wait: 1,
      dns: 0,
      tcp: 0,
      tls: 0,
      request: 0,
      firstByte: 201,
      download: 0,
      total: 202
    }
  },
  options: {
    request: undefined,
    agent: { http: undefined, https: undefined, http2: undefined },
    h2session: undefined,
    decompress: true,
    timeout: {
      connect: undefined,
      lookup: undefined,
      read: undefined,
      request: undefined,
      response: undefined,
      secureConnect: undefined,
      send: undefined,
      socket: undefined
    },
    prefixUrl: '',
    body: '{"tag_name":"1.3.0","description":"## [1.3.0](https://gitlab.com/elfrontboi/gitops/compare/1.2.0...1.3.0) (2025-03-31)\\n\\n### Features\\n\\n* le fix ([0384e78](https://gitlab.com/elfrontboi/gitops/commit/0384e780c18207234dee570bb1b94543726e4da2))\\n","assets":{"links":[]}}',
    form: undefined,
    json: undefined,
    cookieJar: undefined,
    ignoreInvalidCookies: [secure],
    searchParams: undefined,
    dnsLookup: undefined,
    dnsCache: undefined,
    context: {},
    hooks: {
      init: [],
      beforeRequest: [],
      beforeError: [ [Function (anonymous)] ],
      beforeRedirect: [],
      beforeRetry: [],
      afterResponse: []
    },
    followRedirect: true,
    maxRedirects: 10,
    cache: undefined,
    throwHttpErrors: true,
    username: '',
    password: '',
    http2: [secure],
    allowGetBody: [secure],
    headers: {
      'user-agent': 'got (https://github.com/sindresorhus/got)',
      'private-token': '[secure]',
      'content-type': 'application/json',
      'content-length': '270',
      'accept-encoding': 'gzip, deflate, br'
    },
    methodRewriting: [secure],
    dnsLookupIpVersion: undefined,
    parseJson: [Function: parse],
    stringifyJson: [Function: stringify],
    retry: {
      limit: 3,
      methods: [ 'GET', 'PUT', 'HEAD', 'DELETE', 'OPTIONS', 'TRACE' ],
      statusCodes: [
        408, 413, 429, 500,
        502, 503, 504, 521,
        522, 524
      ],
      errorCodes: [
        'ETIMEDOUT',
        'ECONNRESET',
        'EADDRINUSE',
        'ECONNREFUSED',
        'EPIPE',
        'ENOTFOUND',
        'ENETUNREACH',
        'EAI_AGAIN'
      ],
      maxRetryAfter: undefined,
      calculateDelay: [Function: calculateDelay],
      backoffLimit: Infinity,
      noise: 100
    },
    localAddress: undefined,
    method: 'POST',
    createConnection: undefined,
    cacheOptions: {
      shared: undefined,
      cacheHeuristic: undefined,
      immutableMinTimeToLive: undefined,
      ignoreCargoCult: undefined
    },
    https: {
      alpnProtocols: undefined,
      rejectUnauthorized: undefined,
      checkServerIdentity: undefined,
      certificateAuthority: undefined,
      key: undefined,
      certificate: undefined,
      passphrase: undefined,
      pfx: undefined,
      ciphers: undefined,
      honorCipherOrder: undefined,
      minVersion: undefined,
      maxVersion: undefined,
      signatureAlgorithms: undefined,
      tlsSessionLifetime: undefined,
      dhparam: undefined,
      ecdhCurve: undefined,
      certificateRevocationLists: undefined
    },
    encoding: undefined,
    resolveBodyOnly: [secure],
    isStream: [secure],
    responseType: 'text',
    url: URL {
      href: 'https://gitlab.com/api/v4/projects/685139[35](https://gitlab.com/elfrontboi/test/-/jobs/9579480656#L35)/releases',
      origin: 'https://gitlab.com',
      protocol: 'https:',
      username: '',
      password: '',
      host: 'gitlab.com',
      hostname: 'gitlab.com',
      port: '',
      pathname: '/api/v4/projects/68513935/releases',
      search: '',
      searchParams: URLSearchParams {},
      hash: ''
    },
    pagination: {
      transform: [Function: transform],
      paginate: [Function: paginate],
      filter: [Function: filter],
      shouldContinue: [Function: shouldContinue],
      countLimit: Infinity,
      backoff: 0,
      requestLimit: 10000,
      stackAllItems: [secure]
    },
    setHost: true,
    maxHeaderSize: undefined,
    signal: undefined,
    enableUnixSockets: [secure]
  },
  pluginName: '@semantic-release/gitlab',
  [cause]: {}
}
HTTPError: Response code 422 (Ref is not specified)
    at Request.<anonymous> (file:///builds/elfrontboi/test/gitops/templates/semantic-release/node_modules/got/dist/source/as-promise/index.js:92:42)
    at Object.onceWrapper (node:events:633:26)
    at Request.emit (node:events:530:35)
    at Request._onResponseBase (file:///builds/elfrontboi/test/gitops/templates/semantic-release/node_modules/got/dist/source/core/index.js:609:22)
    at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
    at async Request._onResponse (file:///builds/elfrontboi/test/gitops/templates/semantic-release/node_modules/got/dist/source/core/index.js:649:13) {
  input: undefined,
  code: 'ERR_NON_2XX_3XX_RESPONSE',
  timings: {
    start: 1743439[37](https://gitlab.com/elfrontboi/test/-/jobs/9579480656#L37)1130,
    socket: 1743439371131,
    lookup: 1743439371131,
    connect: 1743439371131,
    secureConnect: 1743439371131,
    upload: 1743439371131,
    response: 1743439371332,
    end: 1743439371332,
    error: undefined,
    abort: undefined,
    phases: {
      wait: 1,
      dns: 0,
      tcp: 0,
      tls: 0,
      request: 0,
      firstByte: 201,
      download: 0,
      total: 202
    }
  },
  options: {
    request: undefined,
    agent: { http: undefined, https: undefined, http2: undefined },
    h2session: undefined,
    decompress: true,
    timeout: {
      connect: undefined,
      lookup: undefined,
      read: undefined,
      request: undefined,
      response: undefined,
      secureConnect: undefined,
      send: undefined,
      socket: undefined
    },
    prefixUrl: '',
    body: '{"tag_name":"1.3.0","description":"## [1.3.0](https://gitlab.com/elfrontboi/gitops/compare/1.2.0...1.3.0) (2025-03-31)\\n\\n### Features\\n\\n* le fix ([0[38](https://gitlab.com/elfrontboi/test/-/jobs/9579480656#L38)4e78](https://gitlab.com/elfrontboi/gitops/commit/0384e780c18207234dee570bb1b94543726e4da2))\\n","assets":{"links":[]}}',
    form: undefined,
    json: undefined,
    cookieJar: undefined,
    ignoreInvalidCookies: [secure],
    searchParams: undefined,
    dnsLookup: undefined,
    dnsCache: undefined,
    context: {},
    hooks: {
      init: [],
      beforeRequest: [],
      beforeError: [ [Function (anonymous)] ],
      beforeRedirect: [],
      beforeRetry: [],
      afterResponse: []
    },
    followRedirect: true,
    maxRedirects: 10,
    cache: undefined,
    throwHttpErrors: true,
    username: '',
    password: '',
    http2: [secure],
    allowGetBody: [secure],
    headers: {
      'user-agent': 'got (https://github.com/sindresorhus/got)',
      'private-token': '[secure]',
      'content-type': 'application/json',
      'content-length': '270',
      'accept-encoding': 'gzip, deflate, br'
    },
    methodRewriting: [secure],
    dnsLookupIpVersion: undefined,
    parseJson: [Function: parse],
    stringifyJson: [Function: stringify],
    retry: {
      limit: 3,
      methods: [ 'GET', 'PUT', 'HEAD', 'DELETE', 'OPTIONS', 'TRACE' ],
      statusCodes: [
        408, 413, 429, 500,
        502, 503, 504, 521,
        522, 524
      ],
      errorCodes: [
        'ETIMEDOUT',
        'ECONNRESET',
        'EADDRINUSE',
        'ECONNREFUSED',
        'EPIPE',
        'ENOTFOUND',
        'ENETUNREACH',
        'EAI_AGAIN'
      ],
      maxRetryAfter: undefined,
      calculateDelay: [Function: calculateDelay],
      backoffLimit: Infinity,
      noise: 100
    },
    localAddress: undefined,
    method: 'POST',
    createConnection: undefined,
    cacheOptions: {
      shared: undefined,
      cacheHeuristic: undefined,
      immutableMinTimeToLive: undefined,
      ignoreCargoCult: undefined
    },
    https: {
      alpnProtocols: undefined,
      rejectUnauthorized: undefined,
      checkServerIdentity: undefined,
      certificateAuthority: undefined,
      key: undefined,
      certificate: undefined,
      passphrase: undefined,
      pfx: undefined,
      ciphers: undefined,
      honorCipherOrder: undefined,
      minVersion: undefined,
      maxVersion: undefined,
      signatureAlgorithms: undefined,
      tlsSessionLifetime: undefined,
      dhparam: undefined,
      ecdhCurve: undefined,
      certificateRevocationLists: undefined
    },
    encoding: undefined,
    resolveBodyOnly: [secure],
    isStream: [secure],
    responseType: 'text',
    url: URL {
      href: 'https://gitlab.com/api/v4/projects/6851[39](https://gitlab.com/elfrontboi/test/-/jobs/9579480656#L39)35/releases',
      origin: 'https://gitlab.com',
      protocol: 'https:',
      username: '',
      password: '',
      host: 'gitlab.com',
      hostname: 'gitlab.com',
      port: '',
      pathname: '/api/v4/projects/68513935/releases',
      search: '',
      searchParams: URLSearchParams {},
      hash: ''
    },
    pagination: {
      transform: [Function: transform],
      paginate: [Function: paginate],
      filter: [Function: filter],
      shouldContinue: [Function: shouldContinue],
      countLimit: Infinity,
      backoff: 0,
      requestLimit: 10000,
      stackAllItems: [secure]
    },
    setHost: true,
    maxHeaderSize: undefined,
    signal: undefined,
    enableUnixSockets: [secure]
  },
  pluginName: '@semantic-release/gitlab',
  [cause]: {}
}
```

</details>



Pull request:
fix(retry): also handle status code 422 #839
> https://github.com/sindresorhus/got/blob/a359bd385129d2adbc765b52dfbbadac5f54a825/documentation/7-retry.md#retry

This could fix #839. Processing creation of tags could take longer then the time between the API requests. Adding the status code `422` to the retry configuration could solve this problem as it uses three attempts with additional time between the attempts.

Patch:
diff --git a/lib/fail.js b/lib/fail.js
index 0551631..5f878c4 100644
--- a/lib/fail.js
+++ b/lib/fail.js
@@ -24,12 +24,16 @@ export default async (pluginConfig, context) => {
     labels,
     assignee,
     retryLimit,
+    retryStatusCodes,
   } = resolveConfig(pluginConfig, context);
   const { encodedProjectPath, projectApiUrl } = getProjectContext(context, gitlabUrl, gitlabApiUrl, repositoryUrl);
 
   const apiOptions = {
     headers: { "PRIVATE-TOKEN": gitlabToken },
-    retry: { limit: retryLimit },
+    retry: {
+      limit: retryLimit,
+      statusCodes: retryStatusCodes,
+    },
   };
 
   if (failComment === false || failTitle === false) {
diff --git a/lib/publish.js b/lib/publish.js
index 3f92f7e..4a8f951 100644
--- a/lib/publish.js
+++ b/lib/publish.js
@@ -22,10 +22,8 @@ export default async (pluginConfig, context) => {
     nextRelease: { gitTag, gitHead, notes, version },
     logger,
   } = context;
-  const { gitlabToken, gitlabUrl, gitlabApiUrl, assets, milestones, proxy, retryLimit } = resolveConfig(
-    pluginConfig,
-    context
-  );
+  const { gitlabToken, gitlabUrl, gitlabApiUrl, assets, milestones, proxy, retryLimit, retryStatusCodes } =
+    resolveConfig(pluginConfig, context);
   const assetsList = [];
   const { projectPath, projectApiUrl } = getProjectContext(context, gitlabUrl, gitlabApiUrl, repositoryUrl);
 
@@ -49,7 +47,7 @@ export default async (pluginConfig, context) => {
         },
       ],
     },
-    retry: { limit: retryLimit },
+    retry: { limit: retryLimit, statusCodes: retryStatusCodes },
   };
 
   debug("projectPath: %o", projectPath);
diff --git a/lib/resolve-config.js b/lib/resolve-config.js
index 671fcd1..d26dbf3 100644
--- a/lib/resolve-config.js
+++ b/lib/resolve-config.js
@@ -36,6 +36,9 @@ export default (
   }
 ) => {
   const DEFAULT_RETRY_LIMIT = 3;
+  // Added 422 to fix #839
+  // https://github.com/sindresorhus/got/blob/a359bd385129d2adbc765b52dfbbadac5f54a825/documentation/7-retry.md#retry
+  const DEFAULT_RETRY_STATUS_CODES = [408, 413, 422, 429, 500, 502, 503, 504, 521, 522, 524];
   const userGitlabApiPathPrefix = isNil(gitlabApiPathPrefix)
     ? isNil(GL_PREFIX)
       ? GITLAB_PREFIX
@@ -67,6 +70,7 @@ export default (
     labels: isNil(labels) ? "semantic-release" : labels === false ? false : labels,
     assignee,
     retryLimit: retryLimit ?? DEFAULT_RETRY_LIMIT,
+    retryStatusCodes: DEFAULT_RETRY_STATUS_CODES,
   };
 };
 
diff --git a/lib/success.js b/lib/success.js
index 929b6b9..b2ec118 100644
--- a/lib/success.js
+++ b/lib/success.js
@@ -15,12 +15,20 @@ export default async (pluginConfig, context) => {
     commits,
     releases,
   } = context;
-  const { gitlabToken, gitlabUrl, gitlabApiUrl, successComment, successCommentCondition, proxy, retryLimit } =
-    resolveConfig(pluginConfig, context);
+  const {
+    gitlabToken,
+    gitlabUrl,
+    gitlabApiUrl,
+    successComment,
+    successCommentCondition,
+    proxy,
+    retryLimit,
+    retryStatusCodes,
+  } = resolveConfig(pluginConfig, context);
   const { projectApiUrl } = getProjectContext(context, gitlabUrl, gitlabApiUrl, repositoryUrl);
   const apiOptions = {
     headers: { "PRIVATE-TOKEN": gitlabToken },
-    retry: { limit: retryLimit },
+    retry: { limit: retryLimit, statusCodes: retryStatusCodes },
   };
 
   if (successComment === false) {


Test patch:
diff --git a/test/resolve-config.test.js b/test/resolve-config.test.js
index 525e9e4..5f800e7 100644
--- a/test/resolve-config.test.js
+++ b/test/resolve-config.test.js
@@ -18,6 +18,7 @@ const defaultOptions = {
   assignee: undefined,
   proxy: {},
   retryLimit: 3,
+  retryStatusCodes: [408, 413, 422, 429, 500, 502, 503, 504, 521, 522, 524],
 };
 
 test("Returns user config", (t) => {