phalcon/cphalcon · error · ArgumentTypeRequired
Argument at position {} must have a type
Error message
Argument at position {} must have a type What it means
Thrown by Phalcon\Di\Service\Builder::buildParameter() when a constructor/call argument defined in the array-based DI definition has no 'type' key. Every entry under 'arguments' must be an array describing HOW to resolve the value: ['type' => 'service'|'parameter'|'instance', ...]. Without the type the builder cannot decide whether to fetch a service, use a literal, or instantiate a class.
Source
Thrown at phalcon/Di/Service/Builder.zep:209
}
return instance;
}
/**
* Resolves a constructor/call parameter
*
* @return mixed
*/
private function buildParameter(<DiInterface> container, int position, array argument)
{
var type, name, value, instanceArguments;
/**
* All the arguments must have a type
*/
if unlikely !fetch type, argument["type"] {
throw new ArgumentTypeRequired(position);
}
switch type {
/**
* If the argument type is 'service', we obtain the service from the
* DI
*/
case "service":
if unlikely !fetch name, argument["name"] {
throw new MissingParameterKey("name", position);
}
return container->get(name);
/**
* If the argument type is 'parameter', we assign the value as it is
*/
case "parameter":View on GitHub (pinned to b7419de9cd)
Solutions
- Add a 'type' key to the failing argument: 'parameter' for literals, 'service' to resolve another DI service by name, 'instance' to construct a class (Phalcon 5 name; 'class' in Phalcon 3).
- Use the error position (0-based) to find the exact broken element in your 'arguments' array.
- If the value is a plain literal, switch the whole definition to a closure: $di->set('foo', function() { return new Foo('bar'); }) which skips array parsing entirely.
- Validate definitions at boot (see defense) so a mis-typed definition fails during a startup smoke test instead of at first resolve.
Example fix
// before
$di->set(
'invoiceMailer',
[
'className' => \App\InvoiceMailer::class,
'arguments' => [
['value' => 'notifications@example.com'], // no type -> ArgumentTypeRequired
],
]
);
// after
$di->set(
'invoiceMailer',
[
'className' => \App\InvoiceMailer::class,
'arguments' => [
['type' => 'parameter', 'value' => 'notifications@example.com'],
],
]
); Defensive patterns
Strategy: validation
Validate before calling
const DI_ARGUMENT_KEYS = ['service' => 'name', 'parameter' => 'value', 'instance' => 'className'];
function assertValidDiDefinition(array $definition, string $serviceId): void
{
$args = $definition['arguments'] ?? [];
foreach ($args as $position => $arg) {
if (!is_array($arg) || !isset($arg['type'])) {
throw new InvalidArgumentException(sprintf(
'DI service "%s": argument %d has no "type"', $serviceId, $position
));
}
}
}
// at boot, after registering array definitions:
assertValidDiDefinition($di->getDefinition('foo') /* or your source array */, 'foo'); Type guard
function isDiArgumentDefinition(mixed $arg): bool
{
if (!is_array($arg) || !isset($arg['type']) || !is_string($arg['type'])) {
return false;
}
$required = ['service' => 'name', 'parameter' => 'value', 'instance' => 'className'];
return array_key_exists($arg['type'], $required)
&& isset($arg[$required[$arg['type']]);
} Try / catch
try {
$service = $di->get('foo');
} catch (\Phalcon\Di\Exceptions\ArgumentTypeRequired $e) {
// definition bug: log with the service name and fail loudly
$logger->error('DI definition missing argument type: ' . $e->getMessage());
throw $e;
} Prevention
- Validate array definitions at boot with a small schema check (type + required companion key) so failures surface during deploy smoke tests.
- Prefer closure definitions for anything non-trivial - arrays are only worth it for config-driven wiring.
- Keep definitions in one place (config files) and lint them in CI with the same validator used at boot.
When it happens
Trigger: Calling $di->set('foo', ['className' => 'Foo', 'arguments' => [['value' => 'bar']]]) and then resolving the service via $di->get('foo'), $di['foo'], or injecting it into another service. The throw happens at resolve time, not at set() time, because the array definition is parsed lazily.
Common situations: Writing array DI definitions by hand and assuming arguments are plain values (the old string/positional style), migrating from a different container (Symfony/Pimple pass raw values), or copy-pasting a definition and deleting the type line. Also hit when 'arguments' is built dynamically and one element is a scalar/empty array.
Related errors
- Service '{}' is required in parameter on position {}
- Service 'value' is required in parameter on position {}
- Service 'className' is required in parameter on position {}
- Unknown service type in parameter on position {}
- A dependency injection container is required to access the '
AI-assisted analysis of phalcon/cphalcon@b7419de9cd (2026-08-21).
Data as JSON: /api/errors/05eeefdc8e7c7c81.
Report an issue: GitHub.