{"record":{"id":"0c7a3558999da1fd","repo":"can1357/oh-my-pi","slug":"gitlab-duo-agent","errorCode":null,"errorMessage":"gitlab-duo-agent","messagePattern":"gitlab-duo-agent","errorType":"exception","errorClass":"AIError.MissingApiKeyError","httpStatus":null,"severity":"error","filePath":"packages/ai/src/providers/gitlab-duo-workflow.ts","lineNumber":985,"sourceCode":"\trootNamespaceId: string;\n\trestNamespaceId: string;\n\tcreateNamespaceId: string;\n\trestProjectId: string | undefined;\n\tstartPayload: GitLabDuoWorkflowStartRequest;\n\twebSocketProjectId: string | undefined;\n\tworkflowConnection: GitLabDuoWorkflowDirectAccessConnection;\n\tworkflowId: string;\n\tselectedModelIdentifier: string;\n}\n\nasync function runGitLabDuoWorkflow(\n\tmodel: Model<\"gitlab-duo-agent\">,\n\tcontext: Context,\n\toptions: GitLabDuoWorkflowOptions,\n\tstate: GitLabDuoWorkflowStreamState,\n): Promise<void> {\n\tconst apiKey = options.apiKey;\n\tif (!apiKey) throw new AIError.MissingApiKeyError(\"gitlab-duo-agent\");\n\tconst baseUrl = normalizeGitLabBaseUrl(model.baseUrl || DEFAULT_GITLAB_BASE_URL);\n\tconst fetchImpl = options.fetch ?? fetch;\n\tconst providerSessionState = getGitLabDuoWorkflowProviderSessionState(\n\t\toptions.providerSessionState,\n\t\tbaseUrl,\n\t\tmodel.id,\n\t\toptions.sessionId,\n\t);\n\tstate.providerSessionState = providerSessionState;\n\tconst pendingSession = providerSessionState?.active;\n\tif (pendingSession) {\n\t\thydrateGitLabDuoWorkflowCheckpointState(state, pendingSession);\n\t}\n\tconst pendingActions = pendingSession?.pendingActions;\n\tconst resolvedBatch =\n\t\tpendingSession && pendingActions && pendingActions.length > 0\n\t\t\t? resolveGitLabDuoWorkflowActionBatch(context.messages, pendingActions)\n\t\t\t: undefined;","sourceCodeStart":967,"sourceCodeEnd":1003,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/ai/src/providers/gitlab-duo-workflow.ts#L967-L1003","documentation":"This MissingApiKeyError is thrown at the top of runGitLabDuoWorkflow when options.apiKey is falsy. The GitLab Duo Workflow provider requires a GitLab access token to call the workflow endpoints, and without one nothing can proceed, so the library fails immediately with the provider name as the message.","triggerScenarios":"Calling stream with model id 'gitlab-duo-agent' without supplying apiKey in the provider options and without any ambient credential source resolving one — e.g. no GITLAB token in env, no keychain entry, empty string in config.","commonSituations":"Forgot to set the GitLab personal access token env var; token set under a different variable name than the provider reads; apiKey passed as empty string after a failed env lookup; running in CI where the secret was not injected.","solutions":["Set the GitLab token env variable the provider expects (e.g. GITLAB_TOKEN) or pass apiKey explicitly in options","Create a GitLab personal access token with the required api scope if you don't have one","Verify the token isn't an empty string — a failed env lookup can yield \"\" which is still falsy","Check your config/profile file for a misspelled key name so the credential loader finds it"],"exampleFix":"// before\nstream({ provider: \"gitlab-duo-agent\", ... }) // no apiKey\n// after\nstream({ provider: \"gitlab-duo-agent\", apiKey: process.env.GITLAB_TOKEN, ... })","handlingStrategy":"validation","validationCode":"// Fail fast before calling the provider:\nfunction requireGitlabApiKey(options: { apiKey?: string }): string {\n  const key = options.apiKey ?? process.env.GITLAB_TOKEN;\n  if (!key) throw new Error(\"gitlab-duo-agent requires an apiKey (options.apiKey or GITLAB_TOKEN)\");\n  return key;\n}","typeGuard":"function hasApiKey(o: { apiKey?: string | null }): o is { apiKey: string } {\n  return typeof o.apiKey === \"string\" && o.apiKey.length > 0;\n}","tryCatchPattern":"try {\n  await stream({ provider: \"gitlab-duo-agent\", ...options });\n} catch (err) {\n  if (err instanceof AIError.MissingApiKeyError && err.message === \"gitlab-duo-agent\") {\n    console.error(\"Set GITLAB_TOKEN or pass options.apiKey for gitlab-duo-agent\");\n    process.exitCode = 1;\n  } else throw err;\n}","preventionTips":["Set GITLAB_TOKEN in your shell profile or .env and verify with `echo ${GITLAB_TOKEN:+set}`","Pass apiKey explicitly when constructing provider options instead of relying on ambient lookup","In CI, assert the secret is non-empty before the job runs","Create the PAT with api scope and store it in the secret manager"],"tags":["auth","missing-api-key","gitlab","configuration"],"backgroundTag":"missing-api-key","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}