the-benchmarker/web-frameworks · error · InvalidArgumentException
Parameter ' ' of :: should not be null
Error message
Parameter '{$definition->getMeta('name')}' of {$controller}::{$action} should not be null What it means
Hyperf's FastServer route-parameter parser (parseParameters) builds the argument list for a controller action. When a required request parameter has no value, no default, does not allow null, and its name does not resolve to a container entry, it throws this InvalidArgumentException because the action cannot be invoked with a null it declared mandatory.
Solutions
- Have the client send the missing parameter, or make it optional by allowing null or adding a defaultValue in the parameter definition
- Verify the request actually contains the parameter under the exact name the action expects (check typos and content-type handling)
- Change the action signature so the parameter is nullable or has a documented default when it is legitimately optional
- Return a clean 400 validation response instead of a 500 by validating input before dispatch or mapping this exception in the exception handler
Example fix
// before
public function show(string $id) { ... } // client omits id
// after
public function show(?string $id = null) {
if ($id === null) {
throw new HyperfValidationValidationException('id is required');
}
...
} Defensive patterns
Strategy: validation
Validate before calling
// before dispatching, ensure required params are present
const REQUIRED: array<string, string> = ['id' => 'query', 'name' => 'body'];
foreach (REQUIRED as $name => $where) {
$value = $where === 'query' ? $request->getQueryParam($name) : $request->getParsedBody()[$name] ?? null;
if ($value === null || $value === '') {
throw new \Hyperf\HttpMessage\Exception\BadRequestHttpException("Missing required parameter: {$name}");
}
} Type guard
function hasParam(?string $value): bool
{
return $value !== null && $value !== '';
} Try / catch
try {
$response = $this->handleFound($route, $request);
} catch (\InvalidArgumentException $e) {
if (str_contains($e->getMessage(), 'should not be null')) {
return $responseFactory->createResponse(400)->withJson(['error' => $e->getMessage()]);
}
throw $e;
} Prevention
- Declare defaults or nullable types for parameters that are legitimately optional
- Keep action parameter names in sync with what the frontend actually sends (contract tests help)
- Add an exception handler that maps this InvalidArgumentException to a 400 instead of a 500
- Document each route's required parameters and lint against client SDK definitions
When it happens
Trigger: A client calls an HTTP route whose action signature declares a parameter with a definition that (a) received no value in the request, (b) has no defaultValue in its metadata, (c) does not allowNull(), and (d) is not a container-managed service — reached via handleFound -> parseParameters.
Common situations: Client omits a required query/body parameter; frontend sends a different parameter name than the action expects (typo or renamed field); middleware stripped the value; a new required parameter was added to the action while old clients still call the endpoint without it.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
AI-assisted analysis of the-benchmarker/web-frameworks@3795a31d72 (2026-09-15).
Data as JSON: /api/errors/9ece72e08e24653f.
Report an issue: GitHub.
Appendix: source
Thrown at php/hyperf/app/Kernel/FastServer.php:143
* Parse the parameters of method definitions, and then bind the specified arguments or
* get the value from DI container, combine to a argument array that should be injected
* and return the array.
*/
protected function parseParameters(string $controller, string $action, array $arguments): array
{
$injections = [];
$definitions = $this->methodDefinitionCollector->getParameters($controller, $action);
foreach ($definitions ?? [] as $pos => $definition) {
$value = $arguments[$pos] ?? $arguments[$definition->getMeta('name')] ?? null;
if ($value === null) {
if ($definition->getMeta('defaultValueAvailable')) {
$injections[] = $definition->getMeta('defaultValue');
} elseif ($definition->allowsNull()) {
$injections[] = null;
} elseif ($this->container->has($definition->getName())) {
$injections[] = $this->container->get($definition->getName());
} else {
throw new \InvalidArgumentException("Parameter '{$definition->getMeta('name')}' "
. "of {$controller}::{$action} should not be null");
}
} else {
$injections[] = $this->normalizer->denormalize($value, $definition->getName());
}
}
return $injections;
}
}
View on GitHub (pinned to 3795a31d72)