Skip to content

Handle Anthropic tool_use retries on ValidationError#1810

Merged
jxnl merged 2 commits into567-labs:mainfrom
kelvin-tran:fix/kelvin-tran/anthropic-tool-use-retries
Sep 15, 2025
Merged

Handle Anthropic tool_use retries on ValidationError#1810
jxnl merged 2 commits into567-labs:mainfrom
kelvin-tran:fix/kelvin-tran/anthropic-tool-use-retries

Conversation

@kelvin-tran
Copy link
Copy Markdown
Contributor

@kelvin-tran kelvin-tran commented Sep 14, 2025

Auto-retry when is not working when using Anthropic Claude tool use because of this error:

Error code: 400 - {'type': 'error', 'error': {'type': 'invalid_request_error', 'message': 'messages.2: `tool_use` ids were found without `tool_result` blocks immediately after: toolu_01KELz18M6qYvnwPEYi9wZKx. Each `tool_use` block must have a corresponding `tool_result` block in the next message.'}, 'request_id': 'req_011CT5ysHdXtzNDMm2WwNgKc'}

This is when first attempt resulted in ValidationError, eg,:

<generation number="1">
<exception>
    1 validation error
...

To Reproduce
Something like the below when the client is instantiated with mode=instructor.Mode.ANTHROPIC_TOOLS or the equivalent:

client.messages.create(
    model=model_id,
    messages=instruct_msgs,
    system=system_prompt,
    response_model=response_model,
)

Expected behavior and fix
That retried requests will contain the tool call result and successful generate responses (whether valid or not)

Root cause
In instructor/core/retry.py line 599, the handle_reask_kwargs() function calls:

exception = InstructorError.from_exception(exception, failed_attempts=failed_attempts)

This converts pydantic ValidationError exceptions to instructor ValidationError exceptions, so by the time the exception reaches reask_anthropic_tools(), it's an instructor ValidationError, not a pydantic one.

Fix Applied

File: instructor/providers/anthropic/utils.py
Change:

        if (
            content.type == "tool_use"
            and isinstance(exception, ValidationError)
            and content.name == exception.title
        ):

to

        if (
            content.type == "tool_use"
            and isinstance(exception, ValidationError | InstructorValidationError)   # should really just be InstructorValidationError, but being safe
            and content.name == exception.title
        ):

Seems only the providers/anthropic/utils.py has the problematic pattern as it is the only provider that:

  • uses isinstance(exception, ValidationError) checks
  • accesses the exception.title attribute
  • imports ValidationError from pydantic

So OpenAI, Mistral, Gemini, Cohere, Cerebras, Fireworks, Writer, XAI, Bedrock, Perplexity, VertexAI seem unaffected.


Important

Fixes auto-retry issue in reask_anthropic_tools() by handling both ValidationError and InstructorValidationError for Anthropic provider.

  • Behavior:
    • Fixes auto-retry issue in reask_anthropic_tools() in utils.py by handling both ValidationError and InstructorValidationError.
    • Ensures tool call results are included in retried requests for Anthropic Claude tool.
  • Exceptions:
    • Imports InstructorValidationError from core.exceptions in utils.py.
    • Updates isinstance check to include InstructorValidationError in reask_anthropic_tools().
  • Scope:
    • Only affects Anthropic provider; other providers like OpenAI, Mistral, etc., are unaffected.

This description was created by Ellipsis for b113c93. You can customize this summary. It will automatically update as commits are pushed.

@kelvin-tran kelvin-tran marked this pull request as ready for review September 15, 2025 02:10
Copy link
Copy Markdown
Contributor

@ellipsis-dev ellipsis-dev Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Important

Looks good to me! 👍

Reviewed everything up to b113c93 in 29 seconds. Click for details.
  • Reviewed 21 lines of code in 1 files
  • Skipped 0 files when reviewing.
  • Skipped posting 1 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. instructor/providers/anthropic/utils.py:161
  • Draft comment:
    Using the union operator (ValidationError | InstructorValidationError) is concise, but consider using a tuple (i.e., isinstance(exception, (ValidationError, InstructorValidationError))) for better compatibility with Python versions < 3.10 if needed.
  • Reason this comment was not posted:
    Confidence changes required: 80% <= threshold 85% None

Workflow ID: wflow_kWOx7kI2oe9JZ86u

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

@kelvin-tran kelvin-tran changed the title handle instructor validation error Handle Anthropic tool_use retries on ValidationError Sep 15, 2025
@kelvin-tran
Copy link
Copy Markdown
Contributor Author

kelvin-tran commented Sep 15, 2025

This is caused by changes in #1804. The InstructorError.from_exception() method that enriches exceptions with failed attempts data effectively creates a different class of ValidationError, such that conditionals (eg, exception handlers/if branches) that use isinstance(e, ValidationError, where ValidationError is the pydantic-type err, no longer work as previously

@jxnl jxnl merged commit c785db2 into 567-labs:main Sep 15, 2025
3 of 11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants