Chuck Errors
Chuck Errors
Section titled “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
Section titled “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)
Section titled “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
Section titled “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
Section titled “Plugin Errors”Upload (Cloudflare R2)
Section titled “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)
Section titled “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
Section titled “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
Section titled “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
Section titled “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.jsonrequires Node 24 LTS. Runnvm usefrom the repository root, then reinstall dependencies.
Logs and Traces
Section titled “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
Section titled “Anchor Docs”- API surface: chuck-api
- Env: chuck-env
- Runbook: chuck-runbook
- On-call: chuck-oncall