Duo Chat shows Error 500 on pages with long URLs exceeding 255 characters

Everyone can contribute. Help move this issue forward while earning points, leveling up and collecting rewards.

Summary

Duo Chat returns a 500 error when used on pages with long URLs (exceeding 255 characters) due to a database check constraint violation in the ai_conversation_messages table for the referer_url field.

Steps to reproduce

  1. Navigate to a GitLab project page with a very long URL (either deeply nested project with a long path, complex query parameters, or hash fragments that exceed 255 characters in total URL length)
  2. Open the Duo Chat interface
  3. Type a question and submit it
  4. Observe the 500 error instead of a normal Duo Chat response

Example Project

Reproduced in gitlab.com:

https://gitlab.com/lkorbasiewicz-ultimate/test-the-very-long-path-name-that-exceeds-255-characters-because-i-need-to-reproduce-an-issue-reported-by-a-very-important-customer-in-the-zendesk-ticket/test/-/new/main/testthelongpath%2Flongdirectoryname%2Fanotherlongdirectoryname

image

What is the current bug behavior?

When using Duo Chat on pages with URLs longer than 255 characters:

  1. The user enters a question into the Duo Chat interface
  2. Upon submitting the question, a 500 error occurs
  3. The server logs show a database check constraint violation (check_f36c73d1d9) on the ai_conversation_messages table
  4. The specific error is: PG::CheckViolation: ERROR: new row for relation "ai_conversation_messages" violates check constraint "check_f36c73d1d9"
  5. The insert operation fails because the referer_url field exceeds the 255 character limit enforced by the database constraint

What is the expected correct behavior?

  1. Duo Chat should work correctly on all GitLab pages, regardless of the URL length
  2. When a URL exceeds 255 characters, the system should truncate it before storing in the database
  3. The user should receive a normal response from Duo Chat with no errors
  4. The database constraint on the referer_url field length should not cause failures visible to end users

Relevant logs and/or screenshots

Exception from server logs:

exception.cause_class
PG::CheckViolation

exception.class
ActiveRecord::StatementInvalid

exception.message
PG::CheckViolation: ERROR:  new row for relation "ai_conversation_messages" violates check constraint "check_f36c73d1d9"

DETAIL:  Failing row contains (974854, 23513, null, 1, 2025-05-02 10:46:18.518105+00, 2025-05-02 10:46:18.518105+00, 1, f, "{\"additional_context\":[]}", "[]", explain, b4a308cf-8c72-42cd-a23c-433b3833825a, bc928fe9-577f-471e-91bb-e4bb51374d0b, https://app.gitlab.barcapint.com/barclays/uscb-rft-data-services...).

Database constraint from db/structure.sql:

CONSTRAINT check_f36c73d1d9 CHECK ((char_length(referer_url) <= 255))

Output of checks

Results of GitLab environment info

Expand for output related to GitLab environment info
Not applicable to this bug report. The issue is related to a database constraint and occurs regardless of the GitLab environment.

Results of GitLab application Check

Expand for output related to the GitLab application check
Not applicable to this bug report. The issue is related to a database constraint and validation logic in the model, not to GitLab application health checks.

Possible fixes

The issue is in the Ai::Conversation::Message model that's missing validation and truncation for the referer_url field.

Proposed solution:

  1. Add validation to the Ai::Conversation::Message model to enforce the 255 character limit:
validates :referer_url, length: { maximum: 255 }
  1. Add a callback to automatically truncate the referer_url if it's too long:
before_validation :truncate_referer_url, if: -> { referer_url.present? }

def truncate_referer_url
  self.referer_url = referer_url.truncate(255, omission: '')
end

This approach ensures that:

  1. The application gracefully handles long URLs by truncating them instead of raising errors
  2. The database constraint is respected without requiring schema changes
  3. The fix is applied at the model level, ensuring it works for all code paths that create chat messages

A similar pattern already exists in the codebase in the BulkImports::Failure model:

def source_url=(url)
  super(url&.truncate(255, omission: ''))
end

Note

This issue was mostly generated with GitLab Workflow, verified and updated by a human (Łukasz Korbasiewicz)

Edited by 🤖 GitLab Bot 🤖