getgrav/grav · error · Pimple\Exception\UnknownIdentifierException

Identifier "%s" is not defined.

Error message

Identifier "%s" is not defined.

What it means

Pimple throws UnknownIdentifierException from Container::offsetGet() when the requested string ID has never been registered. Retrieval does not create a default value; the keys map is populated only by offsetSet(), the constructor, or a service provider.

Source

Thrown at system/src/Pimple/Container.php:130

    }

    /**
     * Gets a parameter or an object.
     *
     * @param string $id The unique identifier for the parameter or object
     *
     * @return mixed The value of the parameter or an object
     *
     * @throws UnknownIdentifierException If the identifier is not defined
     */
    public function offsetGet(mixed $id): mixed
    {
        if (!is_string($id)) {
            throw new InvalidServiceIdentifierException($id);
        }

        if (!isset($this->keys[$id])) {
            throw new UnknownIdentifierException($id);
        }

        if (
            isset($this->raw[$id])
            || !is_object($this->values[$id])
            || isset($this->protected[$this->values[$id]])
            || !method_exists($this->values[$id], '__invoke')
        ) {
            return $this->values[$id];
        }

        if (isset($this->factories[$this->values[$id]])) {
            return $this->values[$id]($this);
        }

        $raw = $this->values[$id];
        $val = $this->values[$id] = $raw($this);
        $this->raw[$id] = $raw;

View on GitHub (pinned to 6040efed04)

Solutions

  1. Correct the service name to the exact registered string.
  2. Call isset($container[$id]) or in_array($id, $container->keys(), true) before dynamic access.
  3. Register the missing ID before it is requested.
  4. If using a PSR-11 ServiceLocator, ensure the ID was included in its constructor whitelist rather than assuming the full container is available.

Example fix

// before
$service = $container['assetss']; // typo, not defined

// after
$id = 'assets';
if (!isset($container[$id])) {
    throw new LogicException(sprintf('Service "%s" is not registered; available: %s', $id, implode(', ', $container->keys())));
}
$service = $container[$id];
Defensive patterns

Strategy: validation

Validate before calling

if (!isset($container[$id])) {
    throw new LogicException(sprintf('Service "%s" is not registered. Defined: %s', $id, implode(', ', $container->keys())));
}
$service = $container[$id];

Try / catch

try {
    $service = $container[$id];
} catch (UnknownIdentifierException $e) {
    if ($optional) {
        return $default;
    }
    throw $e;
}

Prevention

When it happens

Trigger: Executing $container['twigg'] for a service registered as 'twig', fetching a service before its provider has registered it, or requesting an ID that only exists in a different Pimple container or ServiceLocator whitelist.

Common situations: Typos and case differences in Grav service names, a plugin expecting another plugin's service without checking availability, initialization-order bugs, or calling container code with IDs loaded from an outdated configuration file.

Related errors


AI-assisted analysis of getgrav/grav@6040efed04 (2026-08-17). Data as JSON: /api/errors/c2be48dd70a74579. Report an issue: GitHub.