Skill errors
Gestiona el manejo de errores y las respuestas de RFC 7807 Problem Details mapeando excepciones a códigos de estado HTTP y creando recursos de error estructurados.
- Estrellas en GitHub
- 29
- Archivos
- 1
- Último commit
- 22 oct 2026
- Licencia
- —
- Herramientas permitidas
- —
¿Qué hace la skill errors?
errors es una agent skill. Gestiona el manejo de errores y las respuestas de RFC 7807 Problem Details mapeando excepciones a códigos de estado HTTP y creando recursos de error estructurados.
Resumen generado a partir del SKILL.md de la skill.
Sobre la skill errors
Gestionar las respuestas de error de la API y los RFC 7807 Problem Details es lo que hacen los desarrolladores que utilizan API Platform con este SKILL. Permite el mapeo sistemático de excepciones de dominio a códigos de estado HTTP específicos, como 404, 409 o 422. Un agente debería cargar este SKILL cuando un usuario necesite configurar el mapeo de excepciones, manejar violaciones de validación o evitar que los detalles internos del sistema se filtren en las respuestas del cliente.
El SKILL proporciona herramientas para crear recursos de error estructurados mediante el atributo ErrorResource y ProblemExceptionInterface. Esto garantiza que los errores complejos incluyan campos personalizados y URIs estables en lugar de ser simplificados en mensajes básicos. También permite documentar estos errores dentro de OpenAPI/Swagger UI vinculándolos a operaciones específicas. Ya sea que trabajes en Symfony o Laravel, este SKILL ayuda a mantener salidas application/problem+json consistentes y gestiona la visibilidad de los mensajes de error según el código de estado HTTP.
Lo que un agente puede hacer con ella
- 1Mapear excepciones de dominio a códigos de estadoConfigura el sistema para devolver un estado 404 cuando se lance una excepción de producto específica.
- 2Crear recursos de error de dominio estructuradosDefine una clase de error personalizada que incluya campos serializados adicionales, como la cantidad disponible.
- 3Evitar la filtración de mensajes internosAsegura que los mensajes de error sensibles de la base de datos se reemplacen por texto genérico en entornos de producción.
- 4Documentar errores en especificaciones de APIAñade tipos de error específicos a una operación para que aparezcan en la documentación de Swagger UI.
Escrito a partir del SKILL.md de la skill. Cada caso de uso se verifica con una cita del mismo.
Cómo instalar la skill errors
Cada comando copia la carpeta de la skill al directorio de skills del cliente. Reinicia el cliente o inicia una nueva sesión para cargarla.Instalar la skill errors en Plugin
/plugin marketplace add api-platform/skillset /plugin install api-platform@api-platform-skillset
Instalar la skill errors en Claude Code
~/.claude/skills/errors/SKILL.md
$ npx degit api-platform/skillset/skills/errors ~/.claude/skills/errorsInstalar la skill errors en Claude Code (project)
.claude/skills/errors/SKILL.md
$ npx degit api-platform/skillset/skills/errors .claude/skills/errorsInstalar la skill errors en Codex
~/.agents/skills/errors/SKILL.md
$ npx degit api-platform/skillset/skills/errors ~/.agents/skills/errorsInstalar la skill errors en Gemini CLI
~/.gemini/skills/errors/SKILL.md
$ npx degit api-platform/skillset/skills/errors ~/.gemini/skills/errorsInstalar la skill errors en Claude.ai
npx degit api-platform/skillset/skills/errors errors && zip -r errors.zip errors # claude.ai → Customize → Skills → + → Create skill → Upload a skill → errors.zip
SKILL.md
Ver en GitHubError Handling
API Platform converts every thrown exception into a structured error response. With
rfc_7807_compliant_errors (the default since 3.1) errors are emitted as
RFC 7807 Problem Details — application/problem+json for JSON clients, the
Hydra error shape for JSON-LD. You rarely build error bodies by hand; you control
the status code and how much of the message is exposed.
How the status code is chosen
For a thrown exception, API Platform resolves the status in this order (Symfony):
exception_to_statusmapping (global or per-resource/operation) — first match wins- Symfony
HttpExceptionInterface→ its status ApiPlatform\Metadata\Exception\ProblemExceptionInterfacewith a status → use itApiPlatform\Metadata\Exception\HttpExceptionInterface→ its status- Defaults:
RequestExceptionInterface→ 400,ValidationException→ 422 - The status declared on an
#[ErrorResource] - Fallback → 500
Mapping exceptions to status
Throw a plain domain exception from your business layer, then map it. Global config:
# config/packages/api_platform.yaml
api_platform:
exception_to_status:
# keep the defaults — removing them changes built-in behavior
Symfony\Component\Serializer\Exception\ExceptionInterface: 400
ApiPlatform\Validator\Exception\ValidationException: 422
# your mappings
App\Exception\ProductNotFoundException: 404
Doctrine\ORM\OptimisticLockException: 409
Per resource / per operation with exceptionToStatus — operation overrides
resource overrides global:
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Get;
use App\Exception\ProductNotFoundException;
use App\Exception\ProductWasRemovedException;
#[ApiResource(
exceptionToStatus: [ProductNotFoundException::class => 404],
operations: [
new Get(exceptionToStatus: [ProductWasRemovedException::class => 410]),
],
)]
class Product {}
A plain exception mapped this way is flattened — API Platform turns it into an
HttpExceptionand loses any custom properties. To keep structured fields, use an#[ErrorResource](below) instead of a bare exception + mapping.
Domain exceptions thrown from providers/processors
The natural place to raise these is inside a state provider or processor (see state-provider / state-processor) — e.g. a processor that rejects a write because a business invariant fails:
use ApiPlatform\State\ProcessorInterface;
use ApiPlatform\Metadata\Operation;
use App\Exception\InsufficientStockException;
final class OrderProcessor implements ProcessorInterface
{
public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): mixed
{
if ($data->quantity > $this->stock->available($data->sku)) {
throw new InsufficientStockException(); // mapped to 409 via exceptionToStatus
}
// ... persist
}
}
Message scope: don't leak internals
The message handling is status-dependent and is a real security control:
- status >= 500: the message is shown only in dev/test. In production a generic
message replaces it — so a
RuntimeException("DB host db-prod-3 refused")never reaches clients. - status < 500: your message is sent to the client.
So a domain 404/409/422 message is client-visible by design — write those
messages for end users, and never put internal detail in a sub-500 exception.
#[ErrorResource]: structured domain errors
For full control over the body (extra fields, a stable type URI), make the
exception an Error resource. It must implement
ApiPlatform\Metadata\Exception\ProblemExceptionInterface and carry #[ErrorResource]:
use ApiPlatform\Metadata\ErrorResource;
use ApiPlatform\Metadata\Exception\ProblemExceptionInterface;
#[ErrorResource]
class InsufficientStockException extends \Exception implements ProblemExceptionInterface
{
public function getType(): string { return '/errors/insufficient-stock'; }
public function getTitle(): ?string { return 'Insufficient stock'; }
public function getStatus(): ?int { return 409; }
public function getDetail(): ?string { return $this->getMessage(); }
public function getInstance(): ?string { return null; }
public int $availableQuantity = 0; // extra field, serialized into the body
}
By default the normalization context strips trace, file, line, code,
message, traceAsString so a stack trace can't leak through an Error resource.
Override that context only if you deliberately want one of those fields.
Documenting domain errors in OpenAPI
Link an Error resource to an operation with errors: so it appears as a documented
response in the OpenAPI/Swagger UI (the errors param is typed
class-string<ProblemExceptionInterface>[]):
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\GetCollection;
use App\Exception\InsufficientStockException;
#[ApiResource(operations: [
new GetCollection(errors: [InsufficientStockException::class]),
])]
class Order {}
See api-docs for broader OpenAPI customization.
Validation errors (422)
A failed Symfony validation throws ApiPlatform\Validator\Exception\ValidationException,
mapped to 422 with a violations array — each entry pairs the offending
propertyPath with a human message:
{
"@context": "/contexts/ConstraintViolationList",
"@type": "ConstraintViolationList",
"status": 422,
"violations": [
{ "propertyPath": "email", "message": "This value is not a valid email address." }
]
}
To report every malformed field in one 422 instead of failing on the first type
mismatch, enable collect_denormalization_errors (see operations). Validation
constraints and groups themselves are covered by custom-validator and
operations.
Customizing the generic error provider
To reshape all non-validation errors, decorate api_platform.state.error_provider
and build the body from ApiPlatform\State\ApiResource\Error:
use ApiPlatform\Metadata\HttpOperation;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ApiResource\Error;
use ApiPlatform\State\ProviderInterface;
use Symfony\Component\DependencyInjection\Attribute\AsAlias;
#[AsAlias('api_platform.state.error_provider')]
final class ErrorProvider implements ProviderInterface
{
public function provide(Operation $operation, array $uriVariables = [], array $context = []): object
{
$exception = $context['request']->attributes->get('exception');
$status = $operation instanceof HttpOperation ? ($operation->getStatus() ?? 500) : 500;
$error = Error::createFromException($exception, $status);
if ($status >= 500) {
$error->setDetail('Something went wrong'); // belt-and-suspenders against leaks
}
return $error;
}
}
Laravel
The RFC 7807 output, the 422 violations shape, #[ErrorResource] +
ProblemExceptionInterface, and per-resource/operation exceptionToStatus are all
framework-neutral. The differences are configuration and the global error provider:
- The global
exception_to_statusmap lives inconfig/api-platform.php(PHP array), not YAML. It ships withIlluminate\Auth\AuthenticationException => 401andIlluminate\Auth\Access\AuthorizationException => 403— keep these when adding your own. 'error_handler' => ['extend_laravel_handler' => true]lets API Platform format errors raised through Laravel's own handler.- To reshape all non-validation errors, bind your own provider for the error operation
in a service provider instead of the Symfony
#[AsAlias('api_platform.state.error_provider')]decoration shown above; theApiPlatform\State\ApiResource\Errorbody is the same.
Checklist
- Domain exceptions mapped via
exceptionToStatus(operation > resource > global) - Default
exception_to_statusentries kept when adding custom ones - Structured errors use
#[ErrorResource]+ProblemExceptionInterface, not flattened exceptions - No internal detail in sub-500 exception messages (those reach clients)
- Domain errors documented on operations via
errors: - Validation relies on the built-in 422
violationsshape, not a custom one
Archivos de esta skill
1Preguntas sobre la skill errors
¿Cómo instalo la skill errors en Claude Code?
Ejecuta npx degit api-platform/skillset/skills/errors ~/.claude/skills/errors. Claude Code carga las skills desde ~/.claude/skills (todos los proyectos) o .claude/skills (un proyecto) y usa una skill cuando su descripción coincide con la tarea.
¿Qué clientes pueden usar la skill errors?
Cualquier cliente que lea el formato Agent Skills: Claude Code, Codex, Gemini CLI y claude.ai (subir como ZIP). Los scripts de la skill se ejecutan solo donde el cliente permite la ejecución de código.
¿Cómo elige API Platform el código de estado HTTP para una excepción?
Resuelve el estado siguiendo un orden específico: el mapeo exception_to_status, Symfony HttpExceptionInterface, ProblemExceptionInterface, o valores por defecto como 400 para RequestExceptionInterface.
¿Cuál es la diferencia entre mapear una excepción simple y usar un #[ErrorResource]?
Una excepción simple mapeada mediante exception_to_status se convierte en una HttpException, perdiendo las propiedades personalizadas. Usar #[ErrorResource] te permite mantener campos estructurados y datos adicionales en el cuerpo de la respuesta.