{"record":{"id":"fa16051c1233d77a","repo":"Mintplex-Labs/anything-llm","slug":"gitlab-loader-unauthorized-request-for-endpoi","errorCode":null,"errorMessage":"[Gitlab Loader]: Unauthorized request for ${endpoint}. Skipping.","messagePattern":"\\[Gitlab Loader\\]: Unauthorized request for (.+?)\\. Skipping\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"collector/utils/extensions/RepoLoader/GitlabRepo/RepoLoader/index.js","lineNumber":408,"sourceCode":"      });\n\n      if (response.status === 429) {\n        if (retries >= MAX_RETRIES) {\n          console.warn(\n            `[Gitlab Loader]: Rate limit persists for ${endpoint} after ${retries} retries. Skipping.`\n          );\n          return null;\n        }\n        const retryAfter = Number(response.headers.get(\"retry-after\")) || 60;\n        console.warn(\n          `[Gitlab Loader]: Rate limit hit for ${endpoint}. Waiting ${retryAfter}s before retrying...`\n        );\n        await this.#wait(retryAfter * 1000);\n        return this.fetchNextPage(requestData, retries + 1);\n      }\n\n      if (response.status === 401) {\n        console.warn(\n          `[Gitlab Loader]: Unauthorized request for ${endpoint}. Skipping.`\n        );\n        return null;\n      }\n\n      if (!response.ok) {\n        console.warn(\n          `[Gitlab Loader]: Unexpected status ${response.status} for ${endpoint}. Skipping.`\n        );\n        return null;\n      }\n\n      const data = await response.json();\n      if (!Array.isArray(data)) {\n        console.warn(`Unexpected response format for ${endpoint}:`, data);\n        return [];\n      }\n","sourceCodeStart":390,"sourceCodeEnd":426,"githubUrl":"https://github.com/Mintplex-Labs/anything-llm/blob/3aec848f2885144aa8f1e53b9731a04310d5d558/collector/utils/extensions/RepoLoader/GitlabRepo/RepoLoader/index.js#L390-L426","documentation":"A paginated GitLab API request returned 401: the PRIVATE-TOKEN header sent by the loader was rejected. fetchNextPage logs this and returns null, aborting that pagination silently. The token is missing, malformed, expired, or revoked — unlike 403, this is an authentication failure, not a permission one.","triggerScenarios":"Expired/revoked PAT passed as the GitLab access token; token with a trailing newline or space from copy/paste; token from a different GitLab instance than apiBase; loading a private project with no token at all.","commonSituations":"Token rotation policies invalidating stored connector credentials; mistaking a deploy trigger token for an API token; wrong instance URL after migrating GitLab hosts.","solutions":["Create a fresh GitLab personal access token with read_api scope and update the connector config.","Confirm the token belongs to the same GitLab instance as the configured API base URL.","Re-paste the token carefully (no whitespace/newline) and re-run the sync.","If the project is private, ensure a token is provided at all."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Preflight a GitLab PAT before syncing:\nconst resp = await fetch(`${apiBase}/api/v4/user`, {\n  headers: { 'PRIVATE-TOKEN': accessToken },\n});\nif (resp.status === 401) throw new Error('GitLab token invalid — update connector credentials');","typeGuard":null,"tryCatchPattern":"const page = await loader.fetchNextPage(req);\nif (page === null) throw new Error('pagination aborted — verify GitLab token/project access');","preventionTips":["Create PATs with read_api scope and record their expiry dates.","Trim whitespace when storing tokens in connector settings.","Keep apiBase and the token's home instance in sync after migrations.","Preflight the token against /api/v4/user in CI before long sync jobs."],"tags":["gitlab","http-401","access-token","pagination","repo-loader"],"backgroundTag":"http-401-unauthorized","analyzedSha":"3aec848f2885144aa8f1e53b9731a04310d5d558","analyzedAt":"2026-08-18T10:02:21.017Z","contentChangedAt":"2026-08-18T10:02:21.017Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}