Chuck Errors
Chuck Errors
How Strapi reports failures and what each class of error usually means
in this deployment. Strapi 5 returns errors via the
built-in strapi::errors middleware,
which is enabled in apps/chuck/meat/config/middlewares.ts.
Error Envelope
All /api/* errors are JSON of the shape:
{ "data": null, "error": { "status": 404, "name": "NotFoundError", "message": "Not Found", "details": {} }}The name value is the most useful field for grepping logs.
HTTP Errors (Content API)
| Status | error.name | Likely cause | First action |
|---|---|---|---|
| 400 | ValidationError | Required field missing on create/update; regex on slug rejected; component shape mismatch. | Inspect error.details.errors[] — each has path, message. |
| 401 | UnauthorizedError | Missing Authorization: Bearer ... on a protected route; admin session expired. | Confirm consumer is sending STRAPI_TOKEN (brisket: apps/brisket/src/env.js). |
| 403 | ForbiddenError | API token lacks permission for this content type / action; Public role missing find/findOne. | Open /admin → Settings → Users & Permissions → API Tokens / Roles → Public. Re-issue token with required scopes. |
| 404 | NotFoundError | Single-type not yet populated (Strapi returns 404 until a record exists); :id does not exist on a collection type; URL slug typo. | Check the entry exists and is published (every type has draftAndPublish: true). |
| 405 | MethodNotAllowedError | Calling a non-default verb on a default router (e.g. POST /api/blog-section when only find is enabled). | Use the documented verbs in chuck-api. |
| 409 | ConflictError | Unique constraint violation (e.g. duplicate slug). | Pick a unique value. |
| 413 | PayloadTooLargeError | Upload bigger than the configured limit; Strapi default body limit (strapi::body) is 100kb for JSON, larger for multipart. | apps/chuck/meat/config/middlewares.ts registers strapi::body with no override, so Strapi defaults apply. TODO(@marty): confirm whether the runtime deployment injects body-limit overrides via env. |
| 415 | UnsupportedMediaTypeError | Wrong Content-Type on upload; provider mismatch. | Use multipart/form-data for media; application/json otherwise. |
| 422 | ValidationError (alt) | Same as 400 but for entity-service-level validation. | Same triage as 400. |
| 429 | TooManyRequestsError | Rate-limit at the platform layer (Cloudflare / Railway). Strapi itself does not ship a built-in rate limiter in this config. | Inspect upstream proxy. |
| 500 | ApplicationError / InternalServerError | Database connection lost, unhandled plugin error, R2 upload failure. | Logs first, then chuck-runbook. |
| 503 | n/a | Process not ready (boot in progress) or dependency down (DB / R2). | Healthcheck path; restart. |
Content Validation Errors
Field-level validation that the schemas in apps/chuck/meat/src/api/*/content-types/*/schema.json enforce:
required: true— many shared-data fields are required (e.g.welcome-shared-data.websiteName,mobileLogo,description,keywords). Saving without them returns 400ValidationError.regexon slugs —blog.slugandblog-blog.slugenforce^[a-z0-9]+(?:-[a-z0-9]+)*$. Spaces, capitals, or trailing hyphens fail validation.allowedTypeson media —images,files,videosmostly. Uploads of other MIME types are rejected at media validation.- Components marked
repeatable: true, required: true— empty arrays fail (e.g.welcome-faq-section.faqSection).
When debugging an editor-reported “save failed”, grep for the field path
in error.details.errors[*].path and cross-reference the schema file.
Plugin Errors
Upload (Cloudflare R2)
Failures bubble up from strapi-provider-cloudflare-r2 as 500s with
provider messages. Common causes:
Access Denied/403— badCF_ACCESS_KEY_ID/CF_ACCESS_SECRET, or the API token lacksObject:Writeon the bucket.NoSuchBucket—CF_BUCKETdoes not match the configured bucket; check Cloudflare dashboard.- CSP block on the rendered page — uploads succeed but images
refuse to render in the admin or in brisket. Check that
CF_PUBLIC_ACCESS_URLmatches the live R2 public hostname; CSP is built from this inconfig/middlewares.ts. - Timeouts — large media on slow connections. The repo does not
override the
strapi::bodymiddleware inapps/chuck/meat/config/middlewares.ts, so Strapi defaults apply. TODO(@marty): confirm whether the runtime deployment increases the upload body limit at the proxy/Strapi layer.
Email (Nodemailer)
Failures appear at admin-panel “send test email” or on users-permissions password-reset:
ESOCKET/ECONNREFUSED—SMTP_HOST/SMTP_PORTwrong or egress blocked.EAUTH—SMTP_USER/SMTP_PASSWORDrejected.- From address rejected — provider requires a verified sender; the
hard-coded
defaultFrom: "no-reply@foxy.ai"inconfig/plugins.tsmust be a verified address on the upstream provider.
Users-Permissions
The plugin is installed but largely unused. If end-user registration is enabled, expect:
ValidationError: email is already takenValidationError: password is too weakApplicationError: Invalid identifier or password
Database Errors
From pg driver (Postgres) or better-sqlite3:
ECONNREFUSEDon boot —DATABASE_URLhost unreachable, or Postgres not running locally. See chuck-local-dev.password authentication failed—DATABASE_PASSWORDmismatch.relation "..." does not exist— schema drift. Strapi runs migrations on boot; if the DB is older than the code,pnpm strapi build && pnpm startshould reconcile. If not, see chuck-runbook.acquireConnectionTimeout— connection pool exhausted. BumpDATABASE_POOL_MAX(default 10) or investigate slow queries.
Boot Errors
Missing API_TOKEN_SALTetc. — required env not set. See chuck-env.Cannot find module 'strapi-provider-cloudflare-r2'—node_modulesout of sync; re-runpnpm installfromapps/chuck/meat/.- Node engine error —
package.jsonrequiresnode >=18 <=22.x.x. Node 24 is not supported (see chuck-meat Gotchas). Switch withnvm use 22.
Logs and Traces
Strapi uses Koa with the strapi::logger middleware. There is no
OpenTelemetry exporter wired in apps/chuck/meat/config/ (grep -r opentelemetry apps/chuck returns no hits). TODO(@marty): document how
chuck logs reach centralized logging — no log shipper or OTel exporter
is checked in; see operations/observability
for the service-level matrix.
Anchor Docs
- API surface: chuck-api
- Env: chuck-env
- Runbook: chuck-runbook
- On-call: chuck-oncall