{"record":{"id":"86945daeff0378b6","repo":"we-promise/sure","slug":"model-did-not-invoke-tool-name-86945d","errorCode":null,"errorMessage":"Model did not invoke #{TOOL_NAME}","messagePattern":"Model did not invoke #(.+?)","errorType":"exception","errorClass":"Provider::Anthropic::Error","httpStatus":null,"severity":"error","filePath":"app/models/provider/anthropic/provider_merchant_enhancer.rb","lineNumber":111,"sourceCode":"        - Do NOT include the www. subdomain (\"walmart.com\", not \"www.walmart.com\")\n        - Favor null over false positives; only return a URL when 80%+ confident\n        - NEVER return a URL for generic or local-only merchants (\"Local diner\", \"Gas station\", \"ATM withdrawal\")\n      INSTRUCTIONS\n    end\n\n    def user_message\n      <<~MESSAGE.strip_heredoc\n        Enhance the following merchants by identifying each one's website URL:\n\n        ```json\n        #{merchants.to_json}\n        ```\n      MESSAGE\n    end\n\n    def extract_enhancements(response)\n      tool_use = Array(response.content).find { |block| block_type(block) == :tool_use }\n      raise Provider::Anthropic::Error, \"Model did not invoke #{TOOL_NAME}\" unless tool_use\n\n      input = block_input(tool_use)\n      input = JSON.parse(input) if input.is_a?(String)\n      enhanced = input.is_a?(Hash) ? (input[\"merchants\"] || input[:merchants]) : nil\n\n      raise Provider::Anthropic::Error, \"Tool call missing merchants\" unless enhanced.is_a?(Array)\n      enhanced\n    end\n\n    def build_response(enhanced)\n      enhanced.map do |m|\n        EnhancedMerchant.new(\n          merchant_id: m[\"merchant_id\"] || m[:merchant_id],\n          business_url: normalize_value(m[\"business_url\"] || m[:business_url])\n        )\n      end\n    end\n","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/we-promise/sure/blob/e69894adb92547273377398c15f45c979cd9416a/app/models/provider/anthropic/provider_merchant_enhancer.rb#L93-L129","documentation":"ProviderMerchantEnhancer#extract_enhancements scans the response content for a :tool_use block; if none exists it raises \"Model did not invoke report_enhancements\". The enhancer forces the report_enhancements tool so merchant website URLs come back as structured JSON; a prose reply, a truncated response, or a refusal ('I cannot browse') leaves the tool block missing.","triggerScenarios":"enhance_provider_merchants runs and the model answers in text (e.g. listing URLs inline) instead of calling the tool; max_tokens truncation on large merchant batches; a custom endpoint proxy stripping tool_choice; the model refusing because merchant names look like PII.","commonSituations":"Weaker model selected in settings; batches near the 25 cap; gateway dropping tool parameters; transient model behavior that succeeds on retry.","solutions":["Retry the enhancement call once.","Verify tool_choice forcing for report_enhancements in the request via the enhance_provider_merchants Langfuse trace.","Use a current strong model and reduce the merchant batch size if truncation is the cause.","Confirm custom proxies forward tool definitions and tool_choice."],"exampleFix":"# before\nresult = enhancer.enhance\n\n# after\nbegin\n  result = enhancer.enhance\nrescue Provider::Anthropic::Error => e\n  retry if e.message.include?(\"did not invoke\") && (attempts += 1) < 2\n  raise\nend","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"attempts = 0\nbegin\n  result = provider.enhance_provider_merchants(merchants: batch, family: family)\nrescue Provider::Anthropic::Error => e\n  attempts += 1\n  retry if attempts < 2 && e.message.include?(\"did not invoke\")\n  raise\nend","preventionTips":["Use a current strong model and verify tool_choice forcing in the Langfuse trace.","Keep merchant batches small so tool arguments aren't truncated.","Retry once before surfacing an error to the user."],"tags":["anthropic","llm","tool-use","merchants","response-parsing"],"backgroundTag":"llm-tool-call-failure","analyzedSha":"e69894adb92547273377398c15f45c979cd9416a","analyzedAt":"2026-08-21T18:22:41.165Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}