Agora

Errors

Every error class @adonis-agora/media exports, with its stable code, when it is thrown, and which properties it carries — so you can branch on a code instead of a message string.

Every failure the library raises deliberately is a named class with a stable code, exported from the barrel. That gives you two ways to branch — instanceof in TypeScript, or error.code across a boundary that lost the prototype (a job queue, a serialized API response) — and it means no error message is ever load-bearing.

import { MimeNotAllowedError, TransformNotReadyError } from '@adonis-agora/media'

try {
  await media.library.attach({ … })
} catch (error) {
  if (error instanceof MimeNotAllowedError) {
    return response.unsupportedMediaType({
      error: `We accept ${error.accepted.join(', ')} here, not ${error.mimeType}`,
    })
  }
  throw error
}

Content and collections

ErrorCodeThrown whenCarries
MimeNotAllowedErrorE_MEDIA_MIME_NOT_ALLOWEDThe declared MIME type is outside the collection's acceptsMimeTypes — checked before anything is written.collection, mimeType, accepted
ContentTypeMismatchErrorE_MEDIA_CONTENT_TYPE_MISMATCHThe file's real signature disagrees with what the client declared.collection, declaredMimeType, detectedMimeType
ContentSignatureUnrecognizedErrorE_MEDIA_CONTENT_SIGNATURE_UNRECOGNIZEDThe bytes match no known signature, on a collection whose whitelist is fully detectable.collection, declaredMimeType, accepted

MimeNotAllowedError's three properties are what let you build the refusal message rather than restating the whitelist in your controller — the collection config stays the single source of truth, on both ends.

Records and objects

ErrorCodeThrown when
MediaNotFoundErrorE_MEDIA_RECORD_NOT_FOUNDAn operation names a media id no record exists for.
MediaObjectMissingErrorE_MEDIA_OBJECT_MISSINGThe record exists but its object is gone from the disk.
VariantNotFoundErrorE_MEDIA_VARIANT_NOT_FOUNDAn attachment is asked for a variant it never generated.

Conversions and transformers

ErrorCodeThrown when
ConversionNotDefinedErrorE_MEDIA_CONVERSION_NOT_DEFINEDA conversion name the collection doesn't declare is requested.
ConversionArtifactMissingErrorE_MEDIA_CONVERSION_ARTIFACT_MISSINGA conversion with no artifact (a metadata-only transform) is asked for a URL.
ImageProcessorMissingErrorE_MEDIA_IMAGE_PROCESSOR_MISSINGAny conversion is requested with no imageProcessor configured.
TransformerNotDefinedErrorE_MEDIA_TRANSFORMER_NOT_DEFINEDtransform() names a transformer the collection doesn't declare.
TransformNotReadyErrorE_MEDIA_TRANSFORM_NOT_READYA transformer conversion is read before it has been generated.
TransformerConflictErrorE_MEDIA_TRANSFORMER_CONFLICTTwo derivatives in one collection share a name — thrown at boot.
TransformerRuntimeMissingErrorE_MEDIA_TRANSFORMER_RUNTIME_MISSINGA transformer needs a peer or runtime capability the host lacks.
TransformerOutputErrorE_MEDIA_TRANSFORMER_OUTPUT_INVALIDA transformer wrote outside its prefix, or named a bad entry.
HlsSourceUnsupportedErrorE_MEDIA_HLS_SOURCE_UNSUPPORTEDAn HLS source can't be stream-copied and no encoder is available.

See Transformers for the reasoning behind the split between "not defined" and "not ready".

Storage and configuration

ErrorCodeThrown when
DriveNotReadyErrorE_MEDIA_DRIVE_NOT_READYA disk resolution reaches @adonisjs/drive before its manager has booted. Almost always a media call at module scope rather than inside a request or app.booted.
StoreNotConfiguredErrorE_MEDIA_STORE_NOT_CONFIGUREDstore names an entry missing from stores. Not a silent fallback to in-memory — a typo must not quietly swap durable persistence for a process-local Map.
UploadSessionStoreNotConfiguredErrorE_MEDIA_UPLOAD_SESSION_STORE_NOT_CONFIGUREDThe same, for a resumable session store.
UploadNotSupportedErrorE_MEDIA_UPLOAD_NOT_SUPPORTEDmode: 'direct' (or a native move) is asked of a disk that can't do it.

Uploads

ErrorCodeThrown whenCarries
ResumableUploadsNotConfiguredErrorE_MEDIA_RESUMABLE_NOT_CONFIGUREDmedia.resumable is used without uploads.resumable in config.
DirectUploadsNotConfiguredErrorE_MEDIA_DIRECT_NOT_CONFIGUREDmedia.direct is used without uploads.direct in config.
UploadSessionNotFoundErrorE_MEDIA_UPLOAD_SESSION_NOT_FOUNDAn unknown session id. Maps to 404.
UploadSessionExpiredErrorE_MEDIA_UPLOAD_SESSION_EXPIREDThe session's TTL has passed; the native upload is aborted on the way out. Maps to 410.
UploadOffsetConflictErrorE_MEDIA_UPLOAD_OFFSET_CONFLICTA TUS PATCH arrives at the wrong offset. Maps to 409.expected, received
UploadPartSizeErrorE_MEDIA_UPLOAD_PART_SIZEA part size violates S3's rules (5 MiB floor, 10,000-part cap).
UploadPartOutOfRangeErrorE_MEDIA_UPLOAD_PART_OUT_OF_RANGEA part number falls outside 1..totalParts — the client sliced with the wrong part size.partNumber, totalParts
UploadPartsIncompleteErrorE_MEDIA_UPLOAD_PARTS_INCOMPLETEcomplete() is called with parts still unaccounted for. Maps to 409.sessionId, missingParts
UnsafeFileNameErrorE_MEDIA_UNSAFE_FILE_NAMEA client-supplied fileName is not a single, safe path segment — it contains / or \, resolves to ./.., is empty, or carries a control character. Thrown by sanitizeFileName before the name ever reaches a storage key, in MediaLibrary's attach/attachExisting, the default keyFor of DirectUploadHandler/TusUploadHandler, and AttachmentManager#createFromFile.fileName

UploadPartsIncompleteError is the one worth designing a client around. It names the exact missing part numbers, which is precisely what S3 will not tell you — asking it to assemble an incomplete upload returns an opaque InvalidPart after a full round-trip. The built-in direct routes put that array in the 409 body as missingParts, so a client can re-upload just those and retry.

How they become HTTP

The framework-agnostic handlers (DirectUploadHandler, TusUploadHandler) map these onto statuses themselves — the "maps to" column above. Anything unmapped keeps propagating to your app's own exception handler, deliberately: an error the library has no opinion about should not be flattened into a generic 500 on the way out. A DirectUploadPolicy.mapError gets first refusal on all of them.


Next steps

On this page