<h1 align="center">
<a href="https://prompts.chat">
Learn how to debug Instructor applications with hooks, logging, and exception handling. Practical techniques for inspecting inputs, outputs, and retries.
Sign in to like and favorite skills
This guide shows how to quickly inspect inputs/outputs, capture retries, and reproduce failures when working with Instructor. It focuses on practical techniques using hooks, logging, and exception data.
The fastest way to enable debug logging is with the
INSTRUCTOR_DEBUG environment variable:
export INSTRUCTOR_DEBUG=1 python your_script.py
Or inline:
INSTRUCTOR_DEBUG=1 python your_script.py
This automatically enables debug logging with correlation IDs for request tracing.
You can also use the standard Python
logging module for more control:
import logging logging.basicConfig(level=logging.DEBUG) logging.getLogger("instructor").setLevel(logging.DEBUG)
You will see messages for:
messages[a1b2c3d4])Tip: Set a handler/formatter to include timestamps and module names.
Hooks let you tap into key moments without modifying core code:
from instructor.core.hooks import HookName # Attach one or more handlers client.on(HookName.COMPLETION_KWARGS, lambda **kw: print("KWARGS:", kw)) client.on(HookName.COMPLETION_RESPONSE, lambda resp: print("RESPONSE:", type(resp))) client.on(HookName.PARSE_ERROR, lambda e: print("PARSE ERROR:", e)) client.on(HookName.COMPLETION_LAST_ATTEMPT, lambda e: print("LAST ATTEMPT:", e)) client.on(HookName.COMPLETION_ERROR, lambda e: print("COMPLETION ERROR:", e))
Common uses:
kwargs passed to the provider (including mode/tools/response_format).Note: Handlers that accept
**kwargs (or a parameter named _instructor_meta) receive a metadata dict with:
attempt_number, correlation_id, mode, response_model_name.
Add **kwargs to your handler signature to access it:client.on(HookName.COMPLETION_KWARGS, lambda **kw: print(kw.get("_instructor_meta")))
Most parsed models returned by Instructor carry the original provider response for debugging:
model = client.create(...) raw = getattr(model, "_raw_response", None) print(raw)
This is useful for checking provider metadata like token usage, model version, and provider-specific fields.
When all retries are exhausted, an
InstructorRetryException is raised. It includes detailed context:
from instructor.core.exceptions import InstructorRetryException try: client.create(...) except InstructorRetryException as e: print("Attempts:", e.n_attempts) print("Last completion:", e.last_completion) print("Create kwargs:", e.create_kwargs) # reproducible input print("Failed attempts:", e.failed_attempts) # list of (attempt, exception, completion) # If available, a compact trace packet to help debugging if hasattr(e, "trace_packet") and e.trace_packet: print("Trace packet:", e.trace_packet)
Use
e.create_kwargs and e.failed_attempts to craft a minimal reproduction.
import openai import instructor from pydantic import BaseModel class MyModel(BaseModel): # fields... pass client = instructor.from_provider("openai/gpt-5-nano") create_kwargs = { # paste from InstructorRetryException.create_kwargs } try: client.create(response_model=MyModel, **create_kwargs) except Exception as err: # Inspect and iterate raise
This pattern captures the exact inputs that triggered a failure.
strict=True enforces exact schema matches and can surface schema drift early.strict=False to validate non‑strictly.client.create(..., response_model=MyModel, strict=True)
You can pass an integer (attempt count) or a
tenacity retrying object to control behavior:
from tenacity import Retrying, stop_after_attempt, stop_after_delay max_retries = Retrying(stop=stop_after_attempt(3) | stop_after_delay(10)) client.create(..., max_retries=max_retries)
This is helpful when balancing latency and robustness.
If you send images/audio/PDFs or text that may include media paths/URIs, Instructor can convert messages for provider formats.
processing.multimodal.convert_messages runs automatically.messages before and after conversion using the hooks above, and ensure media types/URIs are valid.If you’re using a cache (
cache=...), remember:
model = client.create(..., cache=None)
response_model.model_json_schema() matches what you expect the provider to return.mode is valid for your provider; mismatches can cause parsing failures.MD_JSON), ensure the provider is actually returning a ```json code block.If you need deeper visibility, add a custom handler to write kwargs/responses/errors to disk with a timestamp and correlation id.
You can run a minimal, no‑network example that exercises hooks, logging, and parsing flow using a fake provider function:
examples/debugging/run.pypython examples/debugging/run.py
This script:
instructor.*create with instructor.patch(mode=Mode.JSON)