Documentation Index Fetch the complete documentation index at: https://mintlify.com/charlietyn/openapi-generator/llms.txt
Use this file to discover all available pages before exploring further.
This guide covers edge cases, extreme scenarios, and troubleshooting strategies for production environments.
Config Caching with Runtime env() Usage
Symptom
Changing .env values (e.g., APP_NAME, APP_URL) does not affect generated documentation output.
Cause
Laravel’s config:cache freezes configuration values. Some package code reads env() directly at runtime instead of relying solely on cached config values. When config is cached, these env() calls return null.
Affected Areas
PlaceholderHelper::getProjectName() - Reads APP_NAME via env()
EnvironmentGenerator::buildBaseEnvironmentData() - Reads APP_URL via env()
Mitigation
Prefer config overrides
Instead of relying on .env values, set config values explicitly in config/openapi.php: 'info' => [
'title' => 'My API Documentation' , // Instead of env('APP_NAME')
'version' => '1.0.0' ,
],
'environments' => [
'base' => [
'app_url' => 'https://api.example.com' , // Instead of env('APP_URL')
],
],
Clear config cache after changes
When changing .env values: php artisan config:clear
php artisan openapi:generate
Avoid config cache in development
Only use config:cache in production. In local/staging, keep config uncached to allow dynamic .env changes.
How to Reproduce
# Cache config
php artisan config:cache
# Change APP_NAME in .env
sed -i 's/APP_NAME=.*/APP_NAME=NewName/' .env
# Generate docs
php artisan openapi:generate
# Observe that title in openapi.json still shows old name
cat storage/app/public/openapi/openapi.json | grep '"title"'
How to Test
# Clear cache
php artisan config:clear
# Regenerate
php artisan openapi:generate
# Verify new values appear
cat storage/app/public/openapi/openapi.json | grep '"title"'
Production Impact If you deploy with cached config and rely on env() values, your documentation will show stale or incorrect information. Always set critical values in config files, not .env.
Concurrent Generation Writes to Same Output File
Symptom
Partially written or inconsistent JSON/YAML files in storage/app/public/openapi. Files may contain truncated JSON or mixed content from multiple generations.
Cause
Multiple workers, developers, or CI jobs running openapi:generate simultaneously write to the same output filenames, causing race conditions.
Mitigation
Unique Output Paths
File Locking
Single Queue Worker
Use --output to write to unique file names per job: # Include timestamp or job ID
php artisan openapi:generate --output=/tmp/openapi-$( date +%s ).json
# In CI: use build number
php artisan openapi:generate --output=/tmp/openapi-build-${ CI_BUILD_ID }.json
Implement file locking in your application: use Illuminate\Support\Facades\ Cache ;
if ( Cache :: lock ( 'openapi-generation' , 60 ) -> get ()) {
Artisan :: call ( 'openapi:generate' , [ '--all' => true ]);
Cache :: lock ( 'openapi-generation' ) -> release ();
}
Run generation in a dedicated queue with a single worker: // Job
class GenerateOpenApiJob implements ShouldQueue
{
public $queue = 'docs-generation' ;
public function handle ()
{
Artisan :: call ( 'openapi:generate' , [ '--all' => true ]);
}
}
# Run single worker for docs queue
php artisan queue:work --queue=docs-generation --once
How to Reproduce
# Terminal 1
php artisan openapi:generate --all &
# Terminal 2 (immediately after)
php artisan openapi:generate --all &
# Wait for both to complete, then inspect output
cat storage/app/public/openapi/openapi.json | jq .
# May show JSON parse errors
How to Test
Add file locking and run the same concurrent test. Verify that one generation waits for the other to complete.
Long-Running Queue Workers and Stale Caches
Symptom
Old or stale documentation when running generation from a long-lived queue worker. New routes or validation rules don’t appear in output.
Cause
The generator caches output when openapi.cache.enabled is true. Long-lived workers reuse cached data even after code changes.
Mitigation
Disable cache for queue jobs
class GenerateOpenApiJob implements ShouldQueue
{
public function handle ()
{
Artisan :: call ( 'openapi:generate' , [
'--all' => true ,
'--no-cache' => true , // Force fresh generation
]);
}
}
Reduce cache TTL
For frequently changing APIs, reduce cache time-to-live: 'cache' => [
'enabled' => true ,
'ttl' => 300 , // 5 minutes instead of 1 hour
],
Clear cache on deployment
Add cache clearing to deployment scripts: php artisan cache:clear
php artisan config:clear
php artisan openapi:generate --all
How to Reproduce
# Enable cache with long TTL
php artisan config:set openapi.cache.enabled true
php artisan config:set openapi.cache.ttl 3600
# Generate once
php artisan openapi:generate
# Add a new route
echo "Route::get('new-endpoint', fn() => 'test');" >> routes/api.php
# Regenerate (uses cache)
php artisan openapi:generate
# Verify new route is missing from openapi.json
How to Test
# Regenerate with --no-cache
php artisan openapi:generate --no-cache
# Verify new route appears
cat storage/app/public/openapi/openapi.json | grep 'new-endpoint'
Large Route Sets Causing Timeouts
Symptom
HTTP requests to /documentation/openapi.json time out or return 500 errors. Large applications with hundreds of routes cause generation to exceed PHP execution limits.
Cause
On-demand HTTP generation performs heavy introspection:
Route extraction
FormRequest validation analysis
Model schema reflection
Template processing
For large apps, this exceeds the default 30-60 second timeout.
Mitigation
Generate via CLI
Increase Timeout
Filter Routes
Recommended : Generate docs via CLI and serve static files:# Generate during deployment
php artisan openapi:generate --all
# Symlink to public directory
ln -s storage/app/public/openapi public/docs
Serve from: https://api.example.com/docs/openapi.json
https://api.example.com/docs/postman-all.json
Increase PHP execution time for documentation endpoints: // In RouteServiceProvider or middleware
Route :: prefix ( 'documentation' ) -> group ( function () {
ini_set ( 'max_execution_time' , 300 ); // 5 minutes
Route :: get ( 'openapi.{format}' , [ OpenApiController :: class , 'show' ]);
});
Reduce route count using filters: # API type filtering
curl "http://localhost:8000/documentation/openapi.json?api_type=mobile"
Or exclude internal routes: 'exclude_routes' => [
'horizon.*' ,
'telescope.*' ,
'debugbar.*' ,
'internal.*' ,
],
How to Reproduce
Create a large number of routes:
// routes/api.php
for ( $i = 0 ; $i < 500 ; $i ++ ) {
Route :: get ( "test-{ $i }" , fn () => "test" );
}
# Try HTTP generation
curl http://localhost:8000/documentation/openapi.json
# May timeout or return 504 Gateway Timeout
How to Test
Compare response times:
# With filtering
time curl "http://localhost:8000/documentation/openapi.json?api_type=mobile"
# Without filtering
time curl "http://localhost:8000/documentation/openapi.json"
Performance Benchmarks
50 routes : Less than 1 second
200 routes : 2-5 seconds
500+ routes : 10-30 seconds (consider CLI generation)
Multi-Tenant Deployments
Symptom
OpenAPI info title, server URLs, and environments do not reflect tenant-specific settings. All tenants get the same generic documentation.
Cause
Configuration is global. The generator reads app-level config values, not tenant-specific overrides.
Mitigation
Generate docs per tenant
foreach ( Tenant :: all () as $tenant ) {
$tenant -> run ( function () use ( $tenant ) {
// Override config for this tenant
config ([
'openapi.info.title' => "{ $tenant -> name } API" ,
'openapi.servers' => [
[ 'url' => "https://{ $tenant -> domain }/api" ],
],
'openapi.output_path' => storage_path ( "app/tenants/{ $tenant -> id }/openapi" ),
]);
Artisan :: call ( 'openapi:generate' , [ '--all' => true ]);
});
}
Store per-tenant output
Use tenant-specific output paths: 'output_path' => storage_path ( "app/tenants/{ $tenantId }/openapi" ),
Serve from tenant-specific URLs: https://tenant1.example.com/docs/openapi.json
https://tenant2.example.com/docs/openapi.json
Dynamic HTTP routes
Serve tenant-specific docs via HTTP: Route :: get ( 'documentation/openapi.{format}' , function ( $format ) {
$tenant = tenant ();
$service = app ( OpenApiServices :: class );
// Override config for current tenant
config ([
'openapi.info.title' => "{ $tenant -> name } API" ,
'openapi.servers' => [
[ 'url' => "https://{ $tenant -> domain }/api" ],
],
]);
$spec = $service -> generate (
useCache : true ,
apiTypes : null ,
environment : 'production' ,
generationType : 'openapi'
);
return response () -> json ( $spec );
});
How to Reproduce
// Generate for tenant 1
config ([ 'openapi.info.title' => 'Tenant 1 API' ]);
Artisan :: call ( 'openapi:generate' );
// Generate for tenant 2 (without override)
Artisan :: call ( 'openapi:generate' );
// Observe tenant 2 docs show "Tenant 1 API" title
How to Test
// Generate with per-tenant overrides
foreach ([ 'Tenant 1' , 'Tenant 2' ] as $tenantName ) {
config ([ 'openapi.info.title' => "{ $tenantName } API" ]);
Artisan :: call ( 'openapi:generate' , [
'--output' => storage_path ( "app/{ $tenantName }/openapi.json" ),
]);
}
// Verify each file has correct title
Rate Limiting or Auth Middleware Blocking HTTP Docs
Symptom
401/403/429 responses when accessing /documentation/openapi.json.
Cause
The openapi.routes.middleware stack includes authentication, authorization, or rate limiting middleware.
Mitigation
Remove Middleware
Custom Middleware Stack
Static File Serving
For public documentation: 'routes' => [
'enabled' => true ,
'prefix' => 'documentation' ,
'middleware' => [], // No auth or throttling
],
Create a dedicated middleware group: // app/Http/Kernel.php
protected $middlewareGroups = [
'docs' => [
\Illuminate\Routing\Middleware\ SubstituteBindings :: class ,
// No auth or throttling
],
];
// config/openapi.php
'routes' => [
'middleware' => [ 'docs' ],
],
Serve pre-generated files instead of HTTP generation: php artisan openapi:generate --all
ln -s storage/app/public/openapi public/docs
Configure your web server to serve /docs/* directly without Laravel middleware.
How to Reproduce
// config/openapi.php
'routes' => [
'middleware' => [ 'auth:sanctum' , 'throttle:60,1' ],
],
# Without authentication
curl http://localhost:8000/documentation/openapi.json
# {"message":"Unauthenticated."}
How to Test
Remove middleware and verify access:
'routes' => [
'middleware' => [],
],
curl http://localhost:8000/documentation/openapi.json
# Returns OpenAPI spec
Invalid API Type Filters
Symptom
422 validation error when requesting HTTP documentation with invalid API type.
{
"message" : "The given data was invalid." ,
"errors" : {
"api_type" : [ "Invalid API types: unknown" ]
}
}
Cause
Requested API type is missing, disabled, or misspelled in openapi.api_types.
Mitigation
Verify available types
php artisan tinker
>>> config( 'openapi.api_types' )
Check enabled API types: [
'admin' => [ 'enabled' => true , ... ],
'mobile' => [ 'enabled' => true , ... ],
'site' => [ 'enabled' => false , ... ], // Disabled
]
Enable the API type
In config/openapi.php: 'api_types' => [
'site' => [
'prefix' => 'api' ,
'folder_name' => 'API Public' ,
'enabled' => true , // Changed from false
],
],
Add missing API type
If the type doesn’t exist: 'api_types' => [
'partner' => [
'prefix' => 'partner' ,
'folder_name' => 'Partner API' ,
'enabled' => true ,
],
],
How to Reproduce
curl "http://localhost:8000/documentation/openapi.json?api_type=unknown"
# {"message":"The given data was invalid.", ...}
How to Test
Add the API type to config and retry:
curl "http://localhost:8000/documentation/openapi.json?api_type=partner"
# Returns filtered OpenAPI spec
Template JSON Parsing Failures
Symptom
Generation fails with JSON template errors:
❌ Failed to generate specification
JSON parse error: Syntax error in /path/to/templates/generic/list.json
Cause
Invalid JSON syntax in resources/openapi/templates or missing required fields.
Mitigation
Validate template JSON
Use a JSON validator: jq . resources/openapi/templates/generic/list.json
Or online: jsonlint.com
Enable output validation
In config/openapi-templates.php: 'rendering' => [
'validate_output' => true ,
],
This adds extra validation but slows generation. Use only for debugging.
Check for common issues
Trailing commas : Not allowed in JSON
Unescaped quotes : Must escape " inside strings
Missing braces : Ensure all { have matching }
How to Reproduce
Create invalid JSON in a template:
{
"summary" : "List {{entity_plural}}" ,
"description" : "Missing closing brace"
php artisan openapi:generate
# ❌ Failed to generate specification
# JSON parse error...
How to Test
Fix JSON and regenerate:
{
"summary" : "List {{entity_plural}}" ,
"description" : "Valid JSON"
}
php artisan openapi:generate
# ✅ OpenAPI specification generated!
General Troubleshooting
No routes found matching filters
Cause : Routes don’t match API type prefixes or are excluded.Solution :# Check route list
php artisan route:list --path=admin
# Verify API type prefix
config( 'openapi.api_types.admin.prefix' )
# Check exclusion patterns
config( 'openapi.exclude_routes' )
Placeholders not replaced in output
Cause : Template placeholders don’t match available variables.Solution :Available placeholders:
{{entity_singular}} - e.g., “user”
{{entity_plural}} - e.g., “users”
{{api_type}} - e.g., “admin”
Ensure template uses correct placeholder syntax.
FormRequest validation rules not appearing
Permission denied writing output files
Cause : Output directory not writable.Solution :chmod -R 775 storage/app/public/openapi
chown -R www-data:www-data storage/app/public/openapi
Next Steps
API Reference Explore the programmatic API for custom integrations.
Configuration Reference Detailed configuration options and defaults.