instructure/canvas-lms · error · ArgumentError

Unsupported embedding version #

Error message

Unsupported embedding version #{version}

What it means

SmartSearch.generate_embedding dispatches on an explicit embedding version (EMBEDDING_VERSION is 2: v1 = OpenAI ada-002 HTTP API, v2 = Bedrock cohere.embed-multilingual-v3). Passing any version other than 1 or 2 raises ArgumentError 'Unsupported embedding version'.

Solutions

  1. Use SmartSearch::EMBEDDING_VERSION instead of hardcoding a version literal
  2. Pass version: 1 or version: 2 explicitly (integers, not strings)
  3. If data was embedded with an older/newer version, re-index with the currently supported version
  4. Check for string/integer type confusion in the version parameter

Example fix

# before
embedding = SmartSearch.generate_embedding(text, version: 3)
# after
embedding = SmartSearch.generate_embedding(text, version: SmartSearch::EMBEDDING_VERSION)
Defensive patterns

Strategy: type-guard

Validate before calling

raise ArgumentError, 'version must be 1 or 2' unless [1, 2].include?(version)

Type guard

def valid_embedding_version?(v)
  [1, 2].include?(v)
end

Try / catch

begin
  embedding = SmartSearch.generate_embedding(input, version: version)
rescue ArgumentError => e
  Rails.logger.error("#{e.message}; falling back to EMBEDDING_VERSION")
  embedding = SmartSearch.generate_embedding(input)
end

Prevention

When it happens

Trigger: Calling SmartSearch.generate_embedding(input, version: 3) (or 0, nil, '2' as a string) — e.g. code hardcoding an old/new version instead of using the EMBEDDING_VERSION constant, or persisted records storing a version value that is no longer supported.

Common situations: Upgrading/downgrading Canvas where stored embedding versions no longer match supported ones; copy-pasted code passing literal versions; type confusion passing a string '2' instead of integer 2; testing experimental embedding models by bumping version without implementing the branch.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at lib/smart_search.rb:80

      @search_info.map do |_, proc, _|
        proc.call(course)
      end
    end

    def search_scopes(course, user)
      @search_info.map do |klass, _, proc|
        [klass, proc.call(course, user)]
      end
    end

    def generate_embedding(input, query: false, version: EMBEDDING_VERSION)
      case version
      when 1
        generate_embedding_v1(input)
      when 2
        generate_embedding_v2(input, query)
      else
        raise ArgumentError, "Unsupported embedding version #{version}"
      end
    end

    def generate_embedding_v1(input)
      # NOTE: openai does not differentiate between query and document embeddings
      url = "https://api.openai.com/v1/embeddings"
      headers = {
        "Authorization" => "Bearer #{api_key}",
        "Content-Type" => "application/json"
      }

      data = {
        input:,
        model: "text-embedding-ada-002"
      }

      response = JSON.parse(Net::HTTP.post(URI(url), data.to_json, headers).body)
      raise response["error"]["message"] if response["error"]

View on GitHub (pinned to 1c9f0bb801)