Fix code completion direct access on cloud-connected instances
Fix code completion direct access on cloud-connected instances
What does this MR do and why?
On GitLab.com, POST /api/v4/code_suggestions/direct_access always returns a 400 error:
{
"message": "No Code Completion model provided",
"error": "Please, assign a model to the \"Code completion\" feature settings in your duo settings"
}This happens even when the customer has assigned a model through namespace-level Model Selection. Because of this error, the language server cannot use the direct connection to the AI Gateway and has to fall back to the slower, indirect path through the monolith.
Root cause
!237255 (merged) (19.1) added a guard clause to CodeSuggestionsClient#direct_access_token. It returns the 400 error when there is no Ai::FeatureSetting record for code_completions.
The problem: Ai::FeatureSetting is the Duo Self-Hosted model (instance-level ai_feature_settings table). It only has records on Self-Managed instances where an admin configured Duo Self-Hosted. On GitLab.com this table is empty by design — SaaS model selection is stored in a different model (Ai::ModelSelection::NamespaceFeatureSetting), which is resolved later in the endpoint. So the guard fires for every direct_access request on GitLab.com, and also on Self-Managed 19.1+ instances that use the cloud-connected AI Gateway.
The fix
The missing feature setting is only a real problem when the token request would go to a self-hosted AI Gateway — that is the scenario the error message was written for. So this MR only applies the guard when a self-hosted AI Gateway is configured:
if Gitlab::AiGateway.has_self_hosted_ai_gateway? && !code_completions_feature_settingWithout a self-hosted AI Gateway, the token request falls back to the cloud connector (access_token_url(nil) already handles nil correctly). This restores the behavior we had before 19.1. The helpful error message is kept for the Duo Self-Hosted "unpinned model" case.
A new spec covers the case that was missing before: cloud-connected instance, no Ai::FeatureSetting record → the token is issued through the cloud connector.
References
- Resolves #605887 (closed) (root cause analysis is in this comment)
- Regression introduced in !237255 (merged)
Screenshots or screen recordings
No UI changes.
How to set up and validate locally
Cloud-connected path (the fix)
-
Make sure your GDK has no self-hosted AI Gateway URL configured:
# rails console Gitlab::CurrentSettings.update!(ai_gateway_url: nil) -
Make sure there is no self-hosted feature setting for code completions:
::Ai::FeatureSetting.find_by(feature: :code_completions)&.destroy -
Call the endpoint with a user who has a Duo seat:
curl -X POST -H "Authorization: Bearer $TOKEN" \ "http://gdk.test:3000/api/v4/code_suggestions/direct_access" -
Before this MR: 400
"No Code Completion model provided". After this MR: 201 with a token and connection details.
Self-hosted path (behavior is kept)
-
Configure a self-hosted AI Gateway URL:
Gitlab::CurrentSettings.update!(ai_gateway_url: 'http://localhost:5052') -
Keep the code completions feature setting unpinned (no record).
-
Call the same endpoint — it still returns the 400 error with the clear message, same as before this MR.
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.