{"record":{"id":"0abbd6c3919bc17b","repo":"we-promise/sure","slug":"model-is-required-when-using-a-custom-openai-compa","errorCode":null,"errorMessage":"Model is required when using a custom OpenAI‑compatible provider","messagePattern":"Model is required when using a custom OpenAI‑compatible provider","errorType":"exception","errorClass":"Provider::Openai::Error","httpStatus":null,"severity":"error","filePath":"app/models/provider/openai.rb","lineNumber":31,"sourceCode":"  def self.effective_model\n    ENV.fetch(\"OPENAI_MODEL\") { Setting.openai_model }.presence || DEFAULT_MODEL\n  end\n\n  def self.configured?\n    ENV[\"OPENAI_ACCESS_TOKEN\"].present? || Setting.openai_access_token.present?\n  end\n\n  def initialize(access_token, uri_base: nil, model: nil)\n    client_options = { access_token: access_token }\n    llm_uri_base = uri_base.presence\n    llm_model = model.presence\n    client_options[:uri_base] = llm_uri_base if llm_uri_base.present?\n    client_options[:request_timeout] = ENV.fetch(\"OPENAI_REQUEST_TIMEOUT\", 60).to_i\n\n    @client = ::OpenAI::Client.new(**client_options)\n    @uri_base = llm_uri_base\n    if custom_provider? && llm_model.blank?\n      raise Error, \"Model is required when using a custom OpenAI‑compatible provider\"\n    end\n    @default_model = llm_model.presence || self.class.effective_model\n  end\n\n  def supports_model?(model)\n    # If using custom uri_base, support any model\n    return true if custom_provider?\n\n    # Otherwise, check if model starts with any supported OpenAI prefix\n    SUPPORTED_MODELS.any? { |prefix| model.start_with?(prefix) }\n  end\n\n  def supports_responses_endpoint?\n    return @supports_responses_endpoint if defined?(@supports_responses_endpoint)\n\n    env_override = ENV[\"OPENAI_SUPPORTS_RESPONSES_ENDPOINT\"]\n    if env_override.to_s.present?\n      return @supports_responses_endpoint = ActiveModel::Type::Boolean.new.cast(env_override)","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/we-promise/sure/blob/e69894adb92547273377398c15f45c979cd9416a/app/models/provider/openai.rb#L13-L49","documentation":"Raised in Provider::Openai#initialize when a custom provider (a uri_base was supplied, e.g. an OpenAI-compatible gateway like Ollama, LM Studio, or OpenRouter) is configured without a model. With first-party OpenAI the model can default via OPENAI_MODEL / Setting.openai_model / DEFAULT_MODEL (gpt-4.1), but an arbitrary endpoint has no safe default — the gem would otherwise send requests with a model the gateway does not host. Note the message contains a Unicode non-breaking hyphen in 'OpenAI‑compatible', so match on a regex or a normalized string, not a copy-pasted literal.","triggerScenarios":"Provider::Openai.new(key, uri_base: \"http://localhost:11434/v1\") with no model: argument; Settings UI saving a custom LLM provider base URL while the model field is left blank; OPENAI_MODEL and Setting.openai_model both unset (the default does not apply because custom_provider? short-circuits the fallback).","commonSituations":"Self-hosting an OpenAI-compatible endpoint and forgetting that the model list is provider-specific; copy-pasting an initializer snippet for OpenAI and only changing uri_base; blank-string model coming from a form (model.presence turns '' into nil); matching this message in a rescue and missing because of the invisible U+2011 hyphen.","solutions":["Pass an explicit model the endpoint serves: Provider::Openai.new(key, uri_base: ..., model: \"llama3.1\").","Set OPENAI_MODEL in env (or Setting.openai_model) when wiring a custom provider app-wide.","Add a form-level validation requiring model when uri_base is present so the error never reaches the initializer.","When rescuing this error by message, match a prefix like /^Model is required/ instead of the full string to dodge the non-breaking hyphen."],"exampleFix":"# before\nProvider::Openai.new(api_key, uri_base: setting.uri_base)\n\n# after\nraise ArgumentError, \"model required for custom provider\" if setting.uri_base.present? && setting.model.blank?\nProvider::Openai.new(api_key, uri_base: setting.uri_base, model: setting.model)","handlingStrategy":"validation","validationCode":"if uri_base.present? && model.blank?\n  raise ArgumentError, \"model is required when uri_base is set\"\nend","typeGuard":null,"tryCatchPattern":"begin\n  client = Provider::Openai.new(key, uri_base: base, model: model)\nrescue Provider::Openai::Error\n  flash[:alert] = \"Choose a model for the custom provider\" and render :edit\nend","preventionTips":["Validate 'model present when uri_base present' in the settings form, before the initializer runs.","Default the model field per gateway (Ollama/LM Studio expose /v1/models — list and preselect one).","When matching this message in rescue blocks, use a prefix regex; the string contains a non-breaking hyphen."],"tags":["openai","custom-provider","llm","configuration","model-required"],"backgroundTag":"missing-configuration","analyzedSha":"e69894adb92547273377398c15f45c979cd9416a","analyzedAt":"2026-08-21T18:22:41.165Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}