Documentation Index
Fetch the complete documentation index at: https://docs.instructorphp.com/llms.txt
Use this file to discover all available pages before exploring further.
Troubleshooting
Common issues and their solutions when working with Instructor for Laravel.
Installation Issues
Package Not Found
Error:
Package cognesy/instructor-laravel not found
// @doctest id="077d"
Solution:
Ensure you have the correct package name and your Composer repository cache is up to date:
composer clear-cache
composer require cognesy/instructor-laravel
# @doctest id="e163"
If you are using a private Packagist mirror, verify the package is available in your configured repositories.
Service Provider Not Registered
Error:
Class 'Cognesy\Instructor\Laravel\Facades\StructuredOutput' not found
// @doctest id="0a1c"
Solution:
If auto-discovery is disabled in your composer.json, manually register the provider:
return [
'providers' => [
Cognesy\Instructor\Laravel\InstructorServiceProvider::class,
],
];
// @doctest id="1d23"
If auto-discovery is enabled but the provider is not loading, clear the cached package manifest:
php artisan package:discover
php artisan config:clear
php artisan cache:clear
# @doctest id="4d18"
API Key Issues
Error:
No API key configured for connection 'openai'
// @doctest id="73eb"
Solution:
Add your API key to .env:
OPENAI_API_KEY=sk-your-key-here
// @doctest id="a113"
Then clear the config cache so Laravel picks up the change:
php artisan config:clear
# @doctest id="b09d"
Invalid API Key
Error:
401 Unauthorized: Invalid API key
// @doctest id="c50f"
Solution:
- Verify your API key is correct by checking the provider’s dashboard
- Check that the key has not expired or been revoked
- Ensure the key has the required permissions (some providers require specific scopes)
- Verify there are no extra spaces, newlines, or quotes around the key in
.env
- Run
php artisan instructor:test to confirm the key works
Rate Limiting
Error:
429 Too Many Requests
// @doctest id="95b7"
Solution:
Rate limiting occurs when you exceed the provider’s API call limits. Strategies to mitigate this:
- Implement rate limiting in your application using Laravel’s
RateLimiter
- Upgrade your API plan for higher limits
- Add response caching to reduce redundant API calls
- Spread requests across multiple providers using the
connection() method
use Illuminate\Support\Facades\RateLimiter;
if (RateLimiter::tooManyAttempts('llm-calls', 60)) {
throw new TooManyRequestsException();
}
RateLimiter::hit('llm-calls');
// @doctest id="10f5"
Response Does Not Match Model
Error:
Failed to deserialize response to PersonData
// @doctest id="f616"
Solution:
This usually means the LLM produced JSON that does not conform to your response model’s structure. Improve the extraction by:
- Adding more descriptive property comments (these become schema descriptions)
- Providing few-shot examples
- Increasing max retries so the model gets another chance
final class PersonData
{
public function __construct(
/** The person's full legal name (first and last) */
public readonly string $name,
/** The person's age as a whole number */
public readonly int $age,
) {}
}
$result = StructuredOutput::with(
messages: $text,
responseModel: PersonData::class,
maxRetries: 5, // Increase retries
examples: [...], // Add examples
)->get();
// @doctest id="b7a6"
Validation Failures
Error:
Validation failed after 3 retries
// @doctest id="b255"
Solution:
The LLM repeatedly produced output that did not pass your validation constraints. Check whether:
- Your validation constraints are not too strict for the input data
- The retry prompt gives the LLM enough context to understand the errors
- The max retries count is sufficient
$result = StructuredOutput::with(
messages: $text,
responseModel: MyModel::class,
maxRetries: 5,
retryPrompt: 'Previous response failed: {errors}. Please fix these specific issues.',
)->get();
// @doctest id="dce8"
Review your application logs to see the exact validation errors from each retry attempt.
Null Values for Required Fields
Problem: The LLM returns null for fields you expected to have values.
Solution:
This happens when the input text does not contain enough information for the LLM to populate a field. Strategies:
- Make the input text clearer or more detailed
- Add better property descriptions that explain what to look for
- Use a system prompt that instructs the model to infer values from context
- Mark fields as nullable if they are truly optional
$result = StructuredOutput::with(
messages: $text,
responseModel: MyModel::class,
system: 'Extract all available information. If a field is not found in the text, make a reasonable inference based on context.',
)->get();
// @doctest id="78ce"
Timeout Issues
Request Timeout
Error:
cURL error 28: Operation timed out
// @doctest id="5249"
Solution:
The API call took longer than the configured timeout. This is common with large inputs, complex response models, or heavily loaded provider APIs.
Increase the timeout in configuration:
return [
'http' => [
'timeout' => 300, // 5 minutes
'connect_timeout' => 60,
],
];
// @doctest id="2042"
Or override per-request using options:
$result = StructuredOutput::withOptions([
'timeout' => 300,
])->with(...)->get();
// @doctest id="2f69"
Streaming Timeout
Problem: Streaming requests timeout before the LLM finishes generating.
Solution:
For long-running streaming responses, ensure both the HTTP timeout and PHP’s execution time limit are sufficient:
set_time_limit(0); // Disable PHP timeout for this request
$stream = StructuredOutput::with(...)
->withStreaming()
->stream();
// @doctest id="03a4"
In production, consider running streaming extractions in a queue worker where time limits are typically more generous.
Testing Issues
Fake Not Working
Problem: Real API calls are made despite using fake().
Solution:
Ensure you call fake() before any code that triggers an extraction. The fake replaces the facade’s bound instance, and calls made before the swap reach the real service.
// CORRECT
$fake = StructuredOutput::fake([...]);
$result = $myService->extract(); // Uses fake
// WRONG
$result = $myService->extract(); // Real API call!
$fake = StructuredOutput::fake([...]); // Too late
// @doctest id="9b5b"
Http::fake() Not Mocking
Problem: Http::fake() does not affect Instructor calls.
Solution:
Ensure the HTTP driver is set to 'laravel' in your configuration. If a different driver is configured, the package will not route requests through Laravel’s HTTP client.
return [
'http' => [
'driver' => 'laravel',
],
];
// @doctest id="fff6"
Also verify that your test environment is not overriding this setting via an environment variable.
Slow Responses
Solutions:
- Use a faster model —
gpt-4o-mini is significantly faster than gpt-4o for simple extractions
- Use a fast-inference provider — Groq offers very low latency for supported models
- Enable response caching — avoid redundant calls for identical inputs
- Reduce input size — truncate long inputs to the minimum necessary context
// Use faster provider
$result = StructuredOutput::connection('groq')
->with(...)->get();
// Cache responses
$result = Cache::remember($cacheKey, 3600, fn () =>
StructuredOutput::with(...)->get()
);
// @doctest id="ec73"
High Token Usage
Solutions:
- Use concise system prompts — every token in the prompt counts toward your bill
- Truncate long inputs to the essential content
- Use smaller response models with fewer properties
- Choose a model with a lower per-token cost
// Truncate long text
$text = Str::limit($longText, 8000);
$result = StructuredOutput::with(
messages: $text,
responseModel: MyModel::class,
system: 'Extract data. Be concise.', // Short prompt
)->get();
// @doctest id="fcf3"
Memory Issues
Out of Memory
Error:
Allowed memory size exhausted
// @doctest id="8c19"
Solution:
This can happen when processing many documents in a single request. Strategies:
- Process documents in chunks and allow garbage collection between batches
- Use streaming for large responses
- Dispatch extraction jobs to a queue worker with higher memory limits
// Process in chunks
$documents->chunk(10)->each(function ($chunk) {
foreach ($chunk as $doc) {
$result = StructuredOutput::with(...)
->get();
// Process result immediately
}
gc_collect_cycles();
});
// @doctest id="86a4"
Common Error Messages
| Error | Cause | Solution |
|---|
Connection refused | API endpoint unreachable | Check network, firewall, and API URL |
Invalid JSON | LLM returned malformed JSON | Increase retries, simplify response model |
Model not found | Wrong model name | Check model name spelling in config |
Quota exceeded | API billing limit reached | Upgrade plan or wait for reset |
Context length exceeded | Input + output exceeds model limit | Truncate input or use a model with larger context |
Invalid request | Malformed API request | Check request parameters and model compatibility |
Getting Help
If you are still stuck after trying the solutions above:
-
Check the logs for detailed error information:
tail -f storage/logs/laravel.log
-
Enable debug logging for maximum visibility into what is happening:
// config/instructor.php
'logging' => [
'enabled' => true,
'level' => 'debug',
'preset' => 'default',
],
-
Test the API directly to isolate whether the issue is in your configuration or your code:
php artisan instructor:test --connection=openai
php artisan instructor:test --connection=anthropic --inference
-
Search existing issues on GitHub:
https://github.com/cognesy/instructor-php/issues
-
Open a new issue with:
- PHP version (
php -v)
- Laravel version (
php artisan --version)
- Package version (
composer show cognesy/instructor-laravel)
- Full error message and stack trace
- Minimal reproduction code