instructure/canvas-lms · error · LlmConversation::Errors::ConversationError

Cannot use initial token: account does not have…

Error message

Cannot use initial token: account does not have ai_experiences_v2_auth enabled

What it means

LlmConversation::HttpClient's constructor guards use_initial_token: the initial token from Rails credentials is only permitted for accounts that have the ai_experiences_v2_auth feature flag enabled. If you pass use_initial_token: true with a non-nil account lacking that flag, it raises LlmConversation::Errors::ConversationError immediately at initialization.

Solutions

  1. Enable the ai_experiences_v2_auth feature flag on the account (rails c: account.enable_feature!(:ai_experiences_v2_auth)) or via the account feature settings UI.
  2. Drop use_initial_token: true if the account is meant to use legacy bearer-token auth (credentials.llm_conversation_bearer_token).
  3. Pass account: nil with use_initial_token: true only when you truly want the account-less initial-token path (the guard only fires for a present account).
  4. Align the calling code's auth-mode choice with the account's feature flag state before constructing the client.

Example fix

# before
client = LlmConversation::HttpClient.new(account: account, use_initial_token: true)

# after
if account.feature_enabled?(:ai_experiences_v2_auth)
  client = LlmConversation::HttpClient.new(account: account, use_initial_token: true)
else
  client = LlmConversation::HttpClient.new(account: account)
end
Defensive patterns

Strategy: validation

Validate before calling

raise 'v2 flag required' if account && !account.feature_enabled?(:ai_experiences_v2_auth) && use_initial_token
client = LlmConversation::HttpClient.new(account: account, use_initial_token: use_initial_token)

Type guard

def initial_token_allowed?(account)
  account.nil? || account.feature_enabled?(:ai_experiences_v2_auth)
end

Try / catch

begin
  client = LlmConversation::HttpClient.new(account: account, use_initial_token: true)
rescue LlmConversation::Errors::ConversationError => e
  Rails.logger.warn("initial token unavailable: #{e.message}")
  client = LlmConversation::HttpClient.new(account: account)
end

Prevention

When it happens

Trigger: Calling LlmConversation::HttpClient.new(account: some_account, use_initial_token: true) where some_account.feature_enabled?(:ai_experiences_v2_auth) is false.

Common situations: The feature flag was never turned on (or was turned off) for the account; code written for flag-less accounts was switched to use_initial_token after an account was attached; staging/test accounts differ from production flag state; passing a real account where previously nil was passed.

Related errors


AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15). Data as JSON: /api/errors/4f3cd0b2dc78ecd2. Report an issue: GitHub.

Appendix: source

Thrown at lib/llm_conversation/http_client.rb:33

# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
#

require "net/http"
require "json"
require "uri"

module LlmConversation
  class HttpClient
    def initialize(account: nil, use_initial_token: false)
      @base_url = resolve_base_url
      @account = account
      @v2_auth = account&.feature_enabled?(:ai_experiences_v2_auth)

      if use_initial_token && @account.present? && !@v2_auth
        raise LlmConversation::Errors::ConversationError,
              "Cannot use initial token: account does not have ai_experiences_v2_auth enabled"
      end

      @bearer_token = if use_initial_token
                        Rails.application.credentials.dig(:llm_conversation_service, :initial_token)
                      elsif @v2_auth
                        LlmConversation::TokenCache.get_api_token(@account)
                      else
                        Rails.application.credentials.llm_conversation_bearer_token
                      end
    end

    def get(path)
      request(:get, path)
    end

    def post(path, payload: nil)
      request(:post, path, payload:)

View on GitHub (pinned to 1c9f0bb801)