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
- 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.
- Drop use_initial_token: true if the account is meant to use legacy bearer-token auth (credentials.llm_conversation_bearer_token).
- 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).
- 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
- Check account.feature_enabled?(:ai_experiences_v2_auth) before choosing the initial-token mode
- Keep flag state consistent across environments used by the same code path
- Centralize client construction in a factory that picks the auth mode
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
- Bearer token not configured for LLM Conversation Service
- custom gradebook statuses feature flag is disabled
- discussion_checkpoints feature flag must be enabled
- enhanced_rubrics, rubric_self_assesment and…
- feature flag is disabled
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)