Documentation
SinkTroubleshooting
Updated
A send throws "Sink mail transport is not configured"
The application selected MAIL_MAILER=sink but SINK_URL, SINK_TOKEN or both are empty. Attaching the application from Scalpels writes both. If they are missing, the attach did not complete for that environment or site; check its connection in Scalpels. For an application Scalpels does not manage, generate credentials by hand from the provider's connected-apps screen.
A send throws "Sink mail transport refuses to run in production"
The application's APP_ENV is production and SINK_ALLOW_PRODUCTION is not true. This is the production fuse. If mail from this environment should really be delivered, select a different mailer. If it should really be captured, set SINK_ALLOW_PRODUCTION=true deliberately.
A send fails with HTTP 401
Sink did not accept the credential. /ingest accepts only a live, installation-owned credential with the sink.ingest purpose. Check on the installation credentials page in Sink that the application's credential has not been revoked or rotated. An MCP credential sent to /ingest also gets 401.
If the credential was revoked or lost, disconnect the application in Scalpels and attach it again. Scalpels will not issue a second credential under the same name while the first still exists on Sink; see Attach to an existing app for the repair steps.
A send fails with HTTP 404 or 405
SINK_URL probably ends in /ingest. The client adds /ingest itself, so the request goes to /ingest/ingest. Set SINK_URL to Sink's base URL. The same symptom appears if Sink has a SINK_ROUTE_PREFIX that the application's SINK_URL does not include.
A send fails with HTTP 422
Sink rejected the envelope. The response body says why. The usual cause is a client package newer than the Sink installation, which produces a message ending in "upgrade your Sink server". Update Sink first, then the clients. php artisan sink:update in the sending application reports the mismatch.
Messages arrive without a subject, sender or recipients
The raw message was stored but the parse job has not run. Parsing happens on Sink's managed queue just after each message arrives, so a short delay is normal. If messages stay unparsed:
- check in Laravel Cloud that the Sink environment's managed queue is attached and processing jobs;
- remove any queue variables you added by hand, such as
QUEUE_CONNECTION,SQS_*orSINK_QUEUE_CONNECTION, so Cloud's managed values apply.
A message that fails to parse three times is logged as "Failed to parse Sink message." with its id.
A message has no body or no attachments
Look at its Truncation value. attachments_dropped means the sending client removed attachments to fit under SINK_MAX_MESSAGE_BYTES; headers_only means it sent only the headers. Raise the limit in the sending application if you need the whole message.
Images in a message do not load
The inbox renders bodies in a sandbox that loads only images embedded in the message as data: URLs. Remote images are blocked on purpose. Use View raw source to see the image URLs.
Purge refuses to run
Both the inbox's Purge filtered scope and the MCP purge tool refuse when no filter is set. Enter at least one filter, such as the source app label.
An MCP client gets 401
The direct /mcp path accepts only a live, installation-owned credential with the sink.mcp purpose. An ingest credential is rejected. Create a separate sink.mcp credential; see Agents and MCP.
Older messages have disappeared
Sink deletes messages more than seven days old every hour, and applies any message-count or size cap you set. See Configuration to change the limits.
Storage or the database fails on Cloud
Check the Sink environment for variables you added yourself for a managed resource: DB_*, DB_CONNECTION, AWS_*, FILESYSTEM_DISK, cache or queue settings. Remove them so the values Laravel Cloud injects apply.