Skip to content
Scalpels home

Scalpels is officially launching on October 31, 2026. Special early adopter pricing is available now.

← All documentation

Documentation

Slate

Troubleshooting

Updated

Every API call returns 401

Slate gives no more detail than 401. Check, in order:

  • The subject reference does not match. The credential's subject reference must equal this installation's reference exactly, including case — the host in APP_URL, or SLATE_INSTALLATION_SUBJECT_REF if you set one. The Installation credentials list shows each credential's subject. If the application's host changed, or you changed the variable, issue new credentials against the new reference.
  • The credential is not a slate.sources bearer credential, or it has been revoked.
  • The header is malformed. It must be exactly Authorization: Bearer <token>, with a single space and no other text.

The upload PUT returns 400

Send every header from the headers object in the POST /api/v1/sources response, including If-None-Match: *. Without that header, object storage says the request has headers that were not signed. The slot is also single-use and expires after 15 minutes. To retry, register a new source.

A direct upload stays pending

Slate only notices that an upload has arrived when you call GET /api/v1/sources/{id}. Call it after the PUT, before expires_at. If the slot has already expired, the source cannot recover. The hourly cleanup will mark it failed, so register a new one.

A source is rejected

rejection_reason names the check that failed. The most common are:

  • unsupported_container: the file is not a self-contained MP4, MOV, M4A, WebM, Matroska, MP3, WAV or AAC file, or not a PNG, JPEG or font file matching its declared type. A playlist URL (HLS or DASH) is rejected here too.
  • referenced_media: a QuickTime reference movie that points at other files. Export a self-contained file.
  • resolution_exceeded, duration_exceeded, frame_rate_exceeded, stream_count_exceeded, source_too_large: the file is over a limit in Sources. Downscale, trim or split it first.
  • decode_codec_not_allowed: the file uses a codec outside Slate's allow-list. Transcode it to H.264 or AAC.
  • probe_failed: ffprobe could not read the file.

A remote source never becomes ready

The URL must be HTTPS on port 443, resolve to a public address and serve the file without redirecting. Slate does not follow redirects, so use the final URL rather than a share link that redirects. A source stuck in ingesting for two hours is marked failed by the hourly cleanup.

A source or run never leaves its first status

The queue is not processing jobs. Open the Cloud environment and check that the managed queue is attached and healthy. Renders use the default queue and ingest uses the ingest queue, so both have to be running. The Scalpels Console shows pending and failed queue work for the deployment.

A run is rejected with 422

The reason field says why. See the table in Runs and results. The most common causes are a source that is not ready yet, a canvas other than 1536 × 1024 or 1024 × 1536, and a transitions value other than {"type": "fade", "duration": 1.0}.

A run returns 409 run_id_conflict

That run id has already been submitted. No second render was started. Read GET /api/v1/runs/{id} to find out what happened to the first one. For new work, generate a new UUID.

A highlights run fails with clip_range_invalid

A clip's end is past the end of the source video. Slate only checks the source's length during the render, so the submission was accepted.

Captions make the render fail

This is deliberate. If the caption font cannot be used, Slate fails the render instead of drawing the text in a different font. Check that the font source is a real TTF or OTF file uploaded with a font content type. To check the deployment itself, run php artisan slate:doctor in the environment.

A deploy fails while installing ffmpeg

The build step slate:provision-ffmpeg needs xz and tar in the build image. If they are missing, it stops with Missing required `xz` executable. It also fails if the download does not match its published checksum. Redeploy once the cause is fixed. Do not change the pinned release.

Slate ingest requires an S3-backed default filesystem.

The bucket is not attached to the environment, or a hand-set FILESYSTEM_DISK or AWS_* variable is overriding the one Laravel Cloud injects. Attach the bucket in the Cloud dashboard and delete any of those variables you set yourself. To confirm storage works, run php artisan slate:verify-object-storage.

502 from the API

Laravel Cloud returns 502 while the instance wakes from hibernation. Retry with backoff. When the request was a run submission, retry with the same run id.