Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions src/App.php
Original file line number Diff line number Diff line change
Expand Up @@ -642,7 +642,7 @@ public function execute(Route $route, Request $request, Response $response): sta
$arguments = $this->getArguments($error, $pathValues, $request->getParams());
\call_user_func_array($error->getAction(), $arguments);
} catch (\Throwable $e) {
throw new Exception('Error handler had an error: ' . $e->getMessage(), 500, $e);
throw new Exception('Error handler had an error: ' . $e->getMessage() . "\nStack trace: " . $e->getTraceAsString(), 500, $e);
}
}
}
Expand All @@ -654,7 +654,7 @@ public function execute(Route $route, Request $request, Response $response): sta
$arguments = $this->getArguments($error, $pathValues, $request->getParams());
\call_user_func_array($error->getAction(), $arguments);
} catch (\Throwable $e) {
throw new Exception('Error handler had an error: ' . $e->getMessage(), 500, $e);
throw new Exception('Error handler had an error: ' . $e->getMessage() . "\nStack trace: " . $e->getTraceAsString(), 500, $e);
}
}
}
Expand Down Expand Up @@ -811,7 +811,7 @@ private function runInternal(Request $request, Response $response): static
$arguments = $this->getArguments($error, [], $request->getParams());
\call_user_func_array($error->getAction(), $arguments);
} catch (\Throwable $e) {
throw new Exception('Error handler had an error: ' . $e->getMessage(), 500, $e);
throw new Exception('Error handler had an error: ' . $e->getMessage() . "\nStack trace: " . $e->getTraceAsString(), 500, $e);
}
}
}
Expand Down Expand Up @@ -854,7 +854,7 @@ private function runInternal(Request $request, Response $response): static
$arguments = $this->getArguments($error, [], $request->getParams());
\call_user_func_array($error->getAction(), $arguments);
} catch (\Throwable $e) {
throw new Exception('Error handler had an error: ' . $e->getMessage(), 500, $e);
throw new Exception('Error handler had an error: ' . $e->getMessage() . "\nStack trace: " . $e->getTraceAsString(), 500, $e);
}
}
}
Expand All @@ -869,7 +869,7 @@ private function runInternal(Request $request, Response $response): static
$arguments = $this->getArguments($error, [], $request->getParams());
\call_user_func_array($error->getAction(), $arguments);
} catch (\Throwable $e) {
throw new Exception('Error handler had an error: ' . $e->getMessage(), 500, $e);
throw new Exception('Error handler had an error: ' . $e->getMessage() . "\nStack trace: " . $e->getTraceAsString(), 500, $e);
}
}
}
Expand Down
53 changes: 29 additions & 24 deletions tests/AppTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -718,22 +718,23 @@ public function testErrorHandlerFailure(): void
->error()
->inject('error')
->action(function ($error) {
throw new \Exception('Error handler failed');
throw new Exception('Error handler failed');
});

$route = new Route('GET', '/path');
$route
->action(function () {
throw new \Exception('Route action failed');
throw new Exception('Route action failed');
});

try {
$this->app->execute($route, new Request(), new Response());
$this->fail('Should have thrown an exception');
} catch (\Exception $e) {
$this->assertEquals('Error handler had an error: Error handler failed', $e->getMessage());
} catch (Exception $e) {
$this->assertStringStartsWith('Error handler had an error: Error handler failed', $e->getMessage());
$this->assertStringContainsString('Stack trace:', $e->getMessage());
$this->assertEquals(500, $e->getCode());
$this->assertInstanceOf(\Exception::class, $e->getPrevious());
$this->assertInstanceOf(Exception::class, $e->getPrevious());
$this->assertEquals('Error handler failed', $e->getPrevious()->getMessage());
}
}
Expand All @@ -744,13 +745,13 @@ public function testOptionsHandlerFailure(): void
->error()
->inject('error')
->action(function ($error) {
throw new \Exception('Options error handler failed');
throw new Exception('Options error handler failed');
});

// Set up an options handler that throws
App::options()
->action(function () {
throw new \Exception('Options handler failed');
throw new Exception('Options handler failed');
});

$request = new UtopiaRequestTest();
Expand All @@ -759,8 +760,9 @@ public function testOptionsHandlerFailure(): void
try {
$this->app->run($request, new Response());
$this->fail('Should have thrown an exception');
} catch (\Exception $e) {
$this->assertEquals('Error handler had an error: Options error handler failed', $e->getMessage());
} catch (Exception $e) {
$this->assertStringStartsWith('Error handler had an error: Options error handler failed', $e->getMessage());
$this->assertStringContainsString('Stack trace:', $e->getMessage());
$this->assertEquals(500, $e->getCode());
}
}
Expand All @@ -771,7 +773,7 @@ public function testNotFoundErrorHandlerFailure(): void
$this->app
->error()
->action(function () {
throw new \Exception('404 error handler failed');
throw new Exception('404 error handler failed');
});

$request = new UtopiaRequestTest();
Expand All @@ -781,10 +783,11 @@ public function testNotFoundErrorHandlerFailure(): void
try {
$this->app->run($request, new Response());
$this->fail('Should have thrown an exception');
} catch (\Exception $e) {
$this->assertEquals('Error handler had an error: 404 error handler failed', $e->getMessage());
} catch (Exception $e) {
$this->assertStringStartsWith('Error handler had an error: 404 error handler failed', $e->getMessage());
$this->assertStringContainsString('Stack trace:', $e->getMessage());
$this->assertEquals(500, $e->getCode());
$this->assertInstanceOf(\Exception::class, $e->getPrevious());
$this->assertInstanceOf(Exception::class, $e->getPrevious());
$this->assertEquals('404 error handler failed', $e->getPrevious()->getMessage());
}
}
Expand All @@ -796,23 +799,24 @@ public function testGroupErrorHandlerFailure(): void
->error()
->groups(['api'])
->action(function () {
throw new \Exception('Group error handler failed');
throw new Exception('Group error handler failed');
});

$route = new Route('GET', '/api/test');
$route
->groups(['api'])
->action(function () {
throw new \Exception('Route action failed');
throw new Exception('Route action failed');
});

try {
$this->app->execute($route, new Request(), new Response());
$this->fail('Should have thrown an exception');
} catch (\Exception $e) {
$this->assertEquals('Error handler had an error: Group error handler failed', $e->getMessage());
} catch (Exception $e) {
Copy link

Copilot AI Sep 25, 2025

Choose a reason for hiding this comment

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

Missing fully qualified namespace. Should use \Exception to be consistent with the original code pattern and avoid potential namespace conflicts.

Copilot uses AI. Check for mistakes.
$this->assertStringStartsWith('Error handler had an error: Group error handler failed', $e->getMessage());
$this->assertStringContainsString('Stack trace:', $e->getMessage());
$this->assertEquals(500, $e->getCode());
$this->assertInstanceOf(\Exception::class, $e->getPrevious());
$this->assertInstanceOf(Exception::class, $e->getPrevious());
$this->assertEquals('Group error handler failed', $e->getPrevious()->getMessage());
}
}
Expand All @@ -824,31 +828,32 @@ public function testErrorHandlerChaining(): void
->error()
->groups(['api'])
->action(function () {
throw new \Exception('First error handler failed');
throw new Exception('First error handler failed');
});

$this->app
->error()
->action(function () {
throw new \Exception('Second error handler failed');
throw new Exception('Second error handler failed');
});

$route = new Route('GET', '/api/test');
$route
->groups(['api'])
->action(function () {
throw new \Exception('Original error');
throw new Exception('Original error');
});

try {
$this->app->execute($route, new Request(), new Response());
$this->fail('Should have thrown an exception');
} catch (\Exception $e) {
$this->assertEquals('Error handler had an error: First error handler failed', $e->getMessage());
} catch (Exception $e) {
$this->assertStringStartsWith('Error handler had an error: First error handler failed', $e->getMessage());
$this->assertStringContainsString('Stack trace:', $e->getMessage());
$this->assertEquals(500, $e->getCode());

// Verify the error chain
$this->assertInstanceOf(\Exception::class, $e->getPrevious());
$this->assertInstanceOf(Exception::class, $e->getPrevious());
$this->assertEquals('First error handler failed', $e->getPrevious()->getMessage());
}
}
Expand Down