{"record":{"id":"e932508a8292b48e","repo":"Dokploy/dokploy","slug":"bad-request-e93250","errorCode":"BAD_REQUEST","errorMessage":"Failed to fetch repositories: ${response.statusText}","messagePattern":"Failed to fetch repositories: (.+?)","errorType":"http","errorClass":"TRPCError","httpStatus":400,"severity":"error","filePath":"packages/server/src/utils/providers/gitlab.ts","lineNumber":318,"sourceCode":"\t\tconst allProjects = [];\n\t\tlet page = 1;\n\t\tconst perPage = 100; // GitLab's max per page is 100\n\t\tconst baseUrl = (\n\t\t\tgitlabProvider.gitlabInternalUrl || gitlabProvider.gitlabUrl\n\t\t).replace(/\\/+$/, \"\");\n\n\t\twhile (true) {\n\t\t\tconst response = await fetch(\n\t\t\t\t`${baseUrl}/api/v4/projects?membership=true&page=${page}&per_page=${perPage}`,\n\t\t\t\t{\n\t\t\t\t\theaders: {\n\t\t\t\t\t\tAuthorization: `Bearer ${gitlabProvider.accessToken}`,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (!response.ok) {\n\t\t\t\tthrow new TRPCError({\n\t\t\t\t\tcode: \"BAD_REQUEST\",\n\t\t\t\t\tmessage: `Failed to fetch repositories: ${response.statusText}`,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst projects = await response.json();\n\n\t\t\tif (projects.length === 0) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tallProjects.push(...projects);\n\t\t\tpage++;\n\n\t\t\tconst total = response.headers.get(\"x-total\");\n\t\t\tif (total && allProjects.length >= Number.parseInt(total)) {\n\t\t\t\tbreak;\n\t\t\t}","sourceCodeStart":300,"sourceCodeEnd":336,"githubUrl":"https://github.com/Dokploy/dokploy/blob/546686ea3587f12ec5652217dedd9f7960fb6d15/packages/server/src/utils/providers/gitlab.ts#L300-L336","documentation":"validateGitlabProvider queries the GitLab projects API with the stored Bearer token and wraps any non-2xx response in a BAD_REQUEST tRPC error. The message carries only statusText, so the underlying cause (auth, permissions, group path) is hidden.","triggerScenarios":"Expired access token, token without read_api scope, groupName that doesn't exist or the user isn't a member of, or a GitLab instance that is unreachable/rate-limiting (429).","commonSituations":"Adding a GitLab provider for a group the token can't see; self-hosted GitLab behind a proxy returning 502; rate limits when scanning large groups.","solutions":["Verify groupName is the exact group path (URL-encoded if it contains spaces/slashes)","Refresh the token / re-authorize the provider and retry","Check the OAuth scopes include api or read_api","Inspect response.status and body for 401/403/404/429 to pinpoint the cause"],"exampleFix":"// before\nif (!response.ok) {\n  throw new TRPCError({ code: \"BAD_REQUEST\", message: `Failed to fetch repositories: ${response.statusText}` });\n}\n\n// after\nif (!response.ok) {\n  const body = await response.text();\n  throw new TRPCError({ code: \"BAD_REQUEST\", message: `Failed to fetch repositories: ${response.status} ${body}` });\n}","handlingStrategy":"try-catch","validationCode":"const encoded = encodeURIComponent(groupName.trim());","typeGuard":null,"tryCatchPattern":"try {\n  const repos = await validateGitlabProvider(...);\n} catch (e) {\n  if (e instanceof TRPCError && e.code === 'BAD_REQUEST') {\n    // surface message, suggest re-auth for 401-type causes\n  }\n  throw e;\n}","preventionTips":["Refresh token before validation calls","Verify group membership and exact group path before saving the provider"],"tags":["gitlab","trpc","http","repositories"],"backgroundTag":"api-request-unauthorized","analyzedSha":"546686ea3587f12ec5652217dedd9f7960fb6d15","analyzedAt":"2026-08-27T05:18:58.095Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}