Skill errors
Mengelola penanganan error dan respons RFC 7807 Problem Details dengan memetakan exception ke HTTP status code dan membuat resource error yang terstruktur.
- Bintang GitHub
- 29
- File
- 1
- Commit terakhir
- 22 Okt 2026
- Lisensi
- —
- Tool yang diizinkan
- —
Apa fungsi skill errors?
errors adalah agent skill. Mengelola penanganan error dan respons RFC 7807 Problem Details dengan memetakan exception ke HTTP status code dan membuat resource error yang terstruktur.
Ringkasan dibuat dari SKILL.md skill ini.
Tentang skill errors
Mengelola respons error API dan RFC 7807 Problem Details adalah apa yang dilakukan developer yang menggunakan API Platform dengan SKILL ini. Ini memungkinkan pemetaan sistematis dari domain exception ke HTTP status code tertentu, seperti 404, 409, atau 422. Agent harus memuat skill ini saat pengguna perlu mengonfigurasi exception mapping, menangani pelanggaran validasi, atau mencegah detail sistem internal bocor ke dalam respons client.
Skill ini menyediakan tools untuk membuat error resource terstruktur menggunakan atribut ErrorResource dan ProblemExceptionInterface. Hal ini memastikan bahwa error yang kompleks menyertakan field kustom dan URI yang stabil, alih-alih hanya diubah menjadi pesan sederhana. Skill ini juga mendukung dokumentasi error tersebut di dalam OpenAPI/Swagger UI dengan menghubungkannya ke operasi tertentu. Baik saat bekerja di Symfony maupun Laravel, skill ini membantu menjaga konsistensi output application/problem+json dan mengelola visibilitas pesan error berdasarkan HTTP status code.
Apa yang bisa dilakukan agent dengannya
- 1Petakan domain exception ke status codeKonfigurasikan sistem untuk mengembalikan status 404 saat exception produk tertentu dilemparkan.
- 2Buat domain error resource yang terstrukturDefinisikan class error kustom yang menyertakan field serialisasi tambahan seperti jumlah stok yang tersedia.
- 3Cegah kebocoran pesan internalPastikan pesan error database yang sensitif diganti dengan teks generik di lingkungan production.
- 4Dokumentasikan error dalam spesifikasi APITambahkan tipe error spesifik ke sebuah operasi agar muncul dalam dokumentasi Swagger UI.
Ditulis dari SKILL.md milik skill tersebut. Setiap use case diverifikasi dengan kutipan darinya.
Cara install skill errors
Setiap perintah menyalin folder skill ke direktori skills client. Restart client atau mulai sesi baru untuk memuatnya.Install skill errors di Plugin
/plugin marketplace add api-platform/skillset /plugin install api-platform@api-platform-skillset
Install skill errors di Claude Code
~/.claude/skills/errors/SKILL.md
$ npx degit api-platform/skillset/skills/errors ~/.claude/skills/errorsInstall skill errors di Claude Code (project)
.claude/skills/errors/SKILL.md
$ npx degit api-platform/skillset/skills/errors .claude/skills/errorsInstall skill errors di Codex
~/.agents/skills/errors/SKILL.md
$ npx degit api-platform/skillset/skills/errors ~/.agents/skills/errorsInstall skill errors di Gemini CLI
~/.gemini/skills/errors/SKILL.md
$ npx degit api-platform/skillset/skills/errors ~/.gemini/skills/errorsInstall skill errors di 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
Lihat di 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
Berkas dalam skill ini
1Pertanyaan seputar skill errors
Bagaimana cara install skill errors di Claude Code?
Jalankan npx degit api-platform/skillset/skills/errors ~/.claude/skills/errors. Claude Code memuat skill dari ~/.claude/skills (semua proyek) atau .claude/skills (satu proyek) dan menggunakan skill saat deskripsinya cocok dengan tugas.
Client mana saja yang bisa menggunakan skill errors?
Client apa pun yang membaca format Agent Skills: Claude Code, Codex, Gemini CLI, dan claude.ai (unggah sebagai ZIP). Script dalam skill hanya berjalan di client yang mengizinkan eksekusi kode.
Bagaimana API Platform memilih HTTP status code untuk sebuah exception?
API Platform menentukan status menggunakan urutan tertentu: mapping exception_to_status, Symfony HttpExceptionInterface, ProblemExceptionInterface, atau default seperti 400 untuk RequestExceptionInterface.
Apa perbedaan antara memetakan exception biasa dengan menggunakan #[ErrorResource]?
Exception biasa yang dipetakan melalui exception_to_status akan diubah menjadi HttpException, sehingga kehilangan properti kustomnya. Menggunakan #[ErrorResource] memungkinkan Anda mempertahankan field terstruktur dan data tambahan di dalam response body.