monicahq/monica · error · BadRequestHttpException
$e->getMessage()
Error message
$e->getMessage()
What it means
DeleteFileInStorage is the Laravel listener on the FileDeleted event (contact documents/photos). It first asserts the Uploadcare keys are configured (else EnvVariablesNotSetException), then resolves the file on Uploadcare via Api->file()->fileInfo($file->uuid) before deleting it. Any Uploadcare HttpException from that lookup (404 unknown file, 401/403 bad keys, 429 rate limit) is rethrown as Symfony BadRequestHttpException, which renders as HTTP 400.
Source
Thrown at app/Domains/Contact/ManageDocuments/Listeners/DeleteFileInStorage.php:61
{
if (is_null(config('services.uploadcare.private_key'))) {
throw new EnvVariablesNotSetException;
}
if (is_null(config('services.uploadcare.public_key'))) {
throw new EnvVariablesNotSetException;
}
}
private function getFileFromUploadcare(): void
{
$configuration = Configuration::create(config('services.uploadcare.public_key'), config('services.uploadcare.private_key'));
$this->api = new Api($configuration);
try {
$this->fileInUploadcare = $this->api->file()->fileInfo($this->file->uuid);
} catch (HttpException $e) {
throw new BadRequestHttpException($e->getMessage());
}
}
private function deleteFile(): void
{
$this->api->file()->deleteFile($this->fileInUploadcare);
}
}
View on GitHub (pinned to e08e917341)
Solutions
- Check services.uploadcare.public_key / private_key in .env belong to the same Uploadcare project that received the uploads
- Verify the uuid exists: GET https://api.uploadcare.com/files/{uuid}/ with the same keys
- Make deletion idempotent: treat 404 'file not found' as success and skip the remote delete
- If keys and file are fine, read the wrapped message for 429/5xx and retry after a backoff
Example fix
// before
try {
$this->fileInUploadcare = $this->api->file()->fileInfo($this->file->uuid);
} catch (HttpException $e) {
throw new BadRequestHttpException($e->getMessage());
}
// after
try {
$this->fileInUploadcare = $this->api->file()->fileInfo($this->file->uuid);
} catch (HttpException $e) {
if ($e->getStatusCode() === 404) {
return; // already gone on Uploadcare, nothing to delete
}
throw new BadRequestHttpException($e->getMessage());
} Defensive patterns
Strategy: try-catch
Validate before calling
// Preflight: confirm the file still exists on Uploadcare before triggering deletion
use Illuminate\Support\Facades\Http;
$response = Http::withHeaders([
'Accept' => 'application/vnd.uploadcare-v0.7+json',
])->withToken($signedToken)->get("https://api.uploadcare.com/files/{$file->uuid}/");
if ($response->status() === 404) {
// already deleted upstream: drop the local row without calling the listener
} Try / catch
use Symfony\Component\HttpKernel\Exception\HttpException;
try {
$this->api->file()->fileInfo($file->uuid);
} catch (HttpException $e) {
if ($e->getStatusCode() === 404) {
return; // idempotent delete: file already gone
}
if ($e->getStatusCode() === 429 || $e->getStatusCode() >= 500) {
// transient: retry with backoff, or queue the deletion for later
}
throw $e;
} Prevention
- Treat remote 404 as success so document deletion stays idempotent
- Keep UPLOADCARE_PUBLIC_KEY/UPLOADCARE_PRIVATE_KEY stable per environment; changing projects orphans old files
- Never delete files out-of-band in the Uploadcare dashboard without removing the Monica rows
- Log the uuid and status code when the listener fails so orphaned files are traceable
When it happens
Trigger: Deleting a Contact document whose uuid no longer exists in the Uploadcare project (already deleted from the dashboard), using public/private keys from a different Uploadcare project than the one storing the files, or invalid/rotated keys so fileInfo() fails with 401/403.
Common situations: Env keys changed after files were uploaded (old files belong to the previous project), file removed out-of-band in the Uploadcare dashboard, or the files table's uuid out of sync with Uploadcare.
Related errors
- Could not get address book data.
- No address book found
- The user does not belong to the vault's account.
- The password is not valid.
- Only email can be sent.
AI-assisted analysis of monicahq/monica@e08e917341 (2026-08-17).
Data as JSON: /api/errors/d0f9fe4f56553643.
Report an issue: GitHub.