Skip to main content
All BlindCast libraries return Result<T, E> instead of throwing exceptions. When .ok is false, .error has a code (a string literal) and a message (human-readable description). The CLI uses Unix exit codes instead — see CLI Error Codes below. See Result Type Pattern for how to consume results.

Player — PlayerErrorCode

CodeCauseRemediation
UNSUPPORTED_BROWSERMSE or Web Crypto API not availableCheck isPlayerSupported() before calling createPlayer; show a fallback for unsupported browsers
INVALID_VIDEO_ELEMENTvideoEl is null or not an HTMLVideoElementEnsure the element exists in the DOM before calling createPlayer
INVALID_OPTIONSRequired options are missing or malformedkeyServerUrl must be a valid URL string
MANIFEST_LOAD_FAILEDCould not fetch or parse the HLS manifestCheck that the manifest URL is correct and the CDN is reachable; verify the .m3u8 is valid HLS
KEY_FETCH_FAILEDKey server request failed (network error or non-200 response)Check key server availability and CORS configuration (CORS_ORIGINS must include the player’s origin)
KEY_AUTH_FAILEDKey server returned 401 or 403The keyServerAuth callback is returning an invalid or expired token
KEY_LEASE_EXPIREDLease was revoked or expired and the player could not renew itThe viewer’s access has been terminated; show an appropriate message
DECRYPT_FAILEDSegment decryption failedVerify the manifest’s EXT-X-KEY IV= attribute matches the IV used during encryption
MEDIA_ERRORhls.js media error (codec mismatch, corrupt segment)Check the encrypted segment data is valid; verify the upload completed successfully
NETWORK_ERRORSegment download failed (CDN error, offline)Transient; hls.js will retry automatically within its configured retry limits
PLAYER_DESTROYEDA method was called after destroy()Check that your component isn’t calling player methods after unmounting

Uploader — UploaderErrorCode

CodeCauseRemediation
ENCRYPT_FAILEDSegment encryption failedCheck the contentKey is an AES-128-CBC CryptoKey derived with deriveContentKey
UPLOAD_FAILEDPUT request failed (network error, S3 permission error, presign expired)Check S3 bucket policy; verify presigned URLs have sufficient TTL
PRESIGN_FAILEDPresign endpoint returned an error or non-200 statusCheck the key server’s presign endpoint is enabled and the presignUrl is correct
KEY_FETCH_FAILEDCould not fetch the content key from the key serverCheck key server availability and authentication
INVALID_INPUTSegments array is empty, contentId has invalid characters, or a filename contains ..Use relative filenames (e.g., seg-0.ts); contentId must be [a-zA-Z0-9_-]+
MANIFEST_PARSE_ERRORThe .m3u8 manifest could not be parsedVerify the manifest is valid HLS; check for encoding issues or truncated files
ABORTEDAbortController.abort() was called before or during the uploadExpected when user cancels; handle gracefully in your UI

Key Server — KeyErrorCode

These codes are returned by the key server’s internal derivation logic. The HTTP layer maps them to status codes (400, 401, 403, 500).
CodeCauseRemediation
INVALID_MASTER_KEYmasterKeyBytes is not 16 bytes (128-bit) or 32 bytes (256-bit)Generate with blindcast keygen
INVALID_CONTENT_IDcontentId is empty, exceeds 256 characters, or contains characters outside [a-zA-Z0-9_-]Use URL-safe alphanumeric strings with hyphens and underscores only
INVALID_EPOCHEpoch number is negative or not an integerEpochs are computed automatically; this indicates a client bug
INVALID_SALTSalt is not exactly 32 bytesGenerate with blindcast keygen
DERIVATION_FAILEDHKDF operation returned an errorRare; usually indicates a runtime bug. Check that the master key and salt are valid
KEY_EXPORT_FAILEDThe derived key could not be exportedRare; indicates an internal key state issue
LEASE_REQUIREDLeases are enabled but the request has no X-Lease-Id headerThe player must be configured with a lease object ({ leaseEndpoint }) to send the lease ID. See Player Leases.
LEASE_INVALIDLease ID does not match the expected formatEnsure the lease ID comes from the key server’s POST /keys/leases endpoint
LEASE_NOT_FOUNDLease ID not found in the storeThe lease may have been cleaned up after expiry; the viewer needs to re-acquire
LEASE_EXPIREDLease TTL has passedThe player should have renewed automatically; may indicate a network issue during renewal
LEASE_REVOKEDLease was explicitly revokedAccess has been intentionally terminated; show an appropriate message to the viewer
LEASE_CONTENT_MISMATCHLease was issued for a different contentId than the one being requestedThe player’s lease is scoped to a specific content ID; create a new lease for each content item
LEASE_STORE_ERRORBackend failure (e.g., database timeout, KV unreachable)Check your database connection; this is a 5xx-class error

Crypto (internal) — CryptoErrorCode

These codes come from @blindcast/crypto, which is used internally by the player, uploader, and key server. You’ll see them if you use the crypto package directly.
CodeCauseRemediation
INVALID_KEYKey type or algorithm does not match the operationCheck that you’re using an AES-GCM key with encrypt/decrypt, AES-CBC with encryptSegment/decryptSegment, and AES-KW with wrapKey/unwrapKey
INVALID_IVIV is the wrong lengthAES-CBC requires exactly 16 bytes; AES-GCM requires exactly 12 bytes
DECRYPT_FAILEDCiphertext is corrupt, truncated, or the key/IV don’t match the encrypted dataVerify you’re using the same key and IV that were used to encrypt
UNSUPPORTED_ALGORITHMAlgorithm string is not "AES-CBC", "AES-GCM", or "AES-KW"Pass a valid AesAlgorithm value
KEY_IMPORT_FAILEDJWK is malformed or the requested algorithm/usage does not match the JWK alg fieldCheck that the JWK was exported with exportKey and imported with matching options
KEY_EXPORT_FAILEDKey was created as non-extractableKeys derived server-side are non-extractable by design
KEY_WRAP_FAILEDThe wrapping key is not an AES-KW key, or the target key is not extractableUse generateKey("AES-KW") for the wrapping key; ensure the key to wrap is extractable
OPERATION_ERRORUnexpected error from the Web Crypto APICheck .error.message for the underlying browser error
WEB_CRYPTO_UNAVAILABLEglobalThis.crypto.subtle is not availableUse HTTPS (crypto.subtle requires a secure context); check browser support

CLI exit codes

The CLI uses Unix exit codes, not Result types:
Exit codeMeaningExample
0SuccessEncryption completed, keys generated
1User errorInvalid flags, missing required arguments, bad content ID format
2Runtime errorNetwork failure, S3 permission denied, key server unreachable
Use --json to get structured JSON errors on stderr:
blindcast encrypt ./segments --content-id "invalid content id!" --json 2>error.json
echo $?  # 1

cat error.json
# {"code":"INVALID_CONTENT_ID","message":"Content ID must match [a-zA-Z0-9_-]+"}