{"record":{"id":"8eac1c44875781d5","repo":"we-promise/sure","slug":"model-is-required-when-using-a-custom-anthropic-co","errorCode":null,"errorMessage":"Model is required when using a custom Anthropic-compatible endpoint","messagePattern":"Model is required when using a custom Anthropic-compatible endpoint","errorType":"exception","errorClass":"Provider::Anthropic::Error","httpStatus":null,"severity":"error","filePath":"app/models/provider/anthropic.rb","lineNumber":37,"sourceCode":"    configured_model.presence || DEFAULT_MODEL\n  end\n\n  def self.configured?\n    ENV[\"ANTHROPIC_ACCESS_TOKEN\"].present? ||\n      ENV[\"ANTHROPIC_API_KEY\"].present? ||\n      Setting.anthropic_access_token.present?\n  end\n\n  def initialize(access_token, base_url: nil, model: nil)\n    client_options = { api_key: access_token }\n    client_options[:base_url] = base_url if base_url.present?\n    client_options[:timeout] = ENV.fetch(\"ANTHROPIC_REQUEST_TIMEOUT\", 600).to_i\n\n    @client = ::Anthropic::Client.new(**client_options)\n    @base_url = base_url\n\n    if custom_endpoint? && model.blank?\n      raise Error, \"Model is required when using a custom Anthropic-compatible endpoint\"\n    end\n\n    @default_model = model.presence || DEFAULT_MODEL\n  end\n\n  def supports_model?(model)\n    # Custom endpoints (Bedrock, Vertex, or other Anthropic-compatible proxies)\n    # use their own model-ID conventions — e.g. Bedrock IDs look like\n    # `anthropic.claude-sonnet-4-5-20250929-v1:0`. Mirror the OpenAI provider\n    # and bypass the prefix gate when the caller has wired a custom base_url.\n    return true if custom_endpoint?\n\n    DEFAULT_ANTHROPIC_MODEL_PREFIXES.any? { |prefix| model.to_s.start_with?(prefix) }\n  end\n\n  def provider_name\n    custom_endpoint? ? \"Custom Anthropic-compatible (#{@base_url})\" : \"Anthropic\"\n  end","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/we-promise/sure/blob/e69894adb92547273377398c15f45c979cd9416a/app/models/provider/anthropic.rb#L19-L55","documentation":"Provider::Anthropic#initialize raises Error when a custom base_url is configured (custom_endpoint? is true) but model is blank. When you point the provider at your own Anthropic-compatible gateway (Bedrock, Vertex, OpenRouter-style proxies), model IDs follow that endpoint's conventions (e.g. anthropic.claude-sonnet-4-5-20250929-v1:0), so the provider cannot fall back to DEFAULT_MODEL (\"claude-sonnet-4-6\") and requires an explicit model.","triggerScenarios":"Provider::Anthropic.new(access_token, base_url: \"https://my-proxy.example.com\", model: nil) — or the Settings layer constructing the provider from a custom-endpoint configuration where the model field was left empty. The check runs immediately at construction, before any API call.","commonSituations":"Wiring a Bedrock/Vertex proxy: base_url saved but model field skipped in the settings UI; env var for the model name missing (ANTHROPIC_MODEL unset) while ANTHROPIC_BASE_URL is set; test suite building the provider without a model stub.","solutions":["Set the model in your Anthropic provider settings (the model ID your custom endpoint expects, e.g. an Bedrock inference-profile ID) so the provider is constructed with both base_url and model.","If you instantiate the provider directly, always pass model: together with base_url:.","Verify the Setting that holds the custom model is actually persisted (check the settings UI round-trip, not just the env var).","If you actually want api.anthropic.com, remove the base_url so the default model fallback applies."],"exampleFix":"# before\nProvider::Anthropic.new(token, base_url: \"https://bedrock-proxy.internal\")\n# => Model is required when using a custom Anthropic-compatible endpoint\n\n# after\nProvider::Anthropic.new(token,\n  base_url: \"https://bedrock-proxy.internal\",\n  model: \"anthropic.claude-sonnet-4-5-20250929-v1:0\"\n)","handlingStrategy":"validation","validationCode":"def build_anthropic_provider(setting)\n  raise ArgumentError, \"custom endpoint needs a model\" if setting.base_url.present? && setting.model.blank?\n  Provider::Anthropic.new(setting.access_token, base_url: setting.base_url, model: setting.model)\nend","typeGuard":null,"tryCatchPattern":"begin\n  Provider::Anthropic.new(token, base_url:, model:)\nrescue Provider::Anthropic::Error => e\n  flash.now[:alert] = e.message # surface config error in settings UI\nend","preventionTips":["Make the model field required in the settings form whenever a custom base_url is entered.","Add a model-level validation pairing base_url with model so bad configs can't be saved.","Cover the pairing with a unit test so refactors keep it enforced."],"tags":["anthropic","llm","configuration","custom-endpoint","initialization"],"backgroundTag":"missing-required-config","analyzedSha":"e69894adb92547273377398c15f45c979cd9416a","analyzedAt":"2026-08-21T18:22:41.165Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}