instructure/canvas-lms · error · ArgumentError

Name must be a string

Error message

Name must be a string

What it means

LlmConfig#validate! runs at construction time and raises ArgumentError when the name passed to the initializer is not a String. The library requires every LLM config to carry a human-readable string name.

Solutions

  1. Pass the name as a String to LlmConfig.new.
  2. Coerce at the config-loading boundary (e.g. cfg['name'].to_s or String(cfg['name'])).
  3. Add schema validation to the YAML/JSON config file so missing names fail early.

Example fix

// before
LlmConfig.new(:gpt4, "gpt-4", nil, template, {})
// after
LlmConfig.new("gpt4", "gpt-4", nil, template, {})
Defensive patterns

Strategy: type-guard

Validate before calling

raise ArgumentError, "name must be String" unless name.is_a?(String)
cfg = LlmConfig.new(name, ...)

Type guard

def valid_name?(v) = v.is_a?(String)

Try / catch

begin
  cfg = LlmConfig.new(name, ...)
rescue ArgumentError => e
  Rails.logger.error("Invalid LlmConfig: #{e.message}")
  raise
end

Prevention

When it happens

Trigger: LlmConfig.new(name: nil | symbol | integer | other non-string, ...) — i.e. any constructor call whose first argument is not a String.

Common situations: Loading config from YAML/JSON where name is absent or parsed as another type; passing symbols like :gpt4; dynamically generated configs with nil names.

Related errors


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

Appendix: source

Thrown at app/models/llm_config.rb:63

    new_options.each do |key, value|
      substitutions.each do |placeholder_prefix, sub_value|
        new_options[key] = value.gsub("<#{placeholder_prefix}_PLACEHOLDER>", sub_value.to_s) if value.is_a?(String)
      end
    end

    new_options.each_value do |value|
      if value.is_a?(String) && (remaining_placeholder = value.match(/<\w+_PLACEHOLDER>/))
        raise ArgumentError, "Options still contain placeholder: #{remaining_placeholder[0]}"
      end
    end

    [new_template, new_options]
  end

  private

  def validate!
    raise ArgumentError, "Name must be a string" unless @name.is_a?(String)
    raise ArgumentError, "Model ID must be a string" unless @model_id.is_a?(String)
    raise ArgumentError, "Rate limit must be either nil, or hash with :limit and :period keys" unless @rate_limit.nil? || (@rate_limit.is_a?(Hash) && @rate_limit.keys == %i[limit period])
    raise ArgumentError, "Template must be a string" unless @template.is_a?(String)
    raise ArgumentError, "Options must be a hash" unless @options.is_a?(Hash)
  end
end

View on GitHub (pinned to 1c9f0bb801)